Repository: timebertt/kubernetes-controller-sharding Branch: main Commit: 9494dea08d26 Files: 484 Total size: 6.2 MB Directory structure: gitextract_xbddqqqb/ ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug.md │ │ └── enhancement.md │ ├── PULL_REQUEST_TEMPLATE.md │ ├── release.yaml │ ├── renovate.json5 │ └── workflows/ │ ├── e2e.yaml │ ├── images.yaml │ ├── release-notes.yaml │ ├── renovate.yaml │ └── verify.yaml ├── .gitignore ├── .golangci.yaml ├── .run/ │ ├── experiment (kind).run.xml │ ├── shard (kind).run.xml │ ├── sharder (kind).run.xml │ └── webhosting-operator (kind).run.xml ├── LICENSE ├── Makefile ├── README.md ├── cmd/ │ ├── checksum-controller/ │ │ ├── main.go │ │ └── reconciler.go │ └── sharder/ │ ├── app/ │ │ ├── app.go │ │ └── options.go │ └── main.go ├── config/ │ ├── README.md │ ├── certificate/ │ │ ├── certificate.yaml │ │ ├── issuer.yaml │ │ └── kustomization.yaml │ ├── crds/ │ │ ├── kustomization.yaml │ │ ├── namespace.yaml │ │ └── sharding.timebertt.dev_controllerrings.yaml │ ├── default/ │ │ └── kustomization.yaml │ ├── monitoring/ │ │ ├── kustomization.yaml │ │ ├── prometheus_rbac.yaml │ │ └── servicemonitor.yaml │ ├── rbac/ │ │ ├── kustomization.yaml │ │ ├── leader_election.yaml │ │ ├── metrics_auth.yaml │ │ ├── pprof_reader.yaml │ │ ├── role.yaml │ │ ├── rolebinding.yaml │ │ └── serviceaccount.yaml │ └── sharder/ │ ├── config.yaml │ ├── deployment.yaml │ ├── kustomization.yaml │ ├── poddisruptionbudget.yaml │ └── service.yaml ├── docs/ │ ├── README.md │ ├── design.md │ ├── development.md │ ├── evaluation.md │ ├── getting-started.md │ ├── implement-sharding.md │ ├── installation.md │ └── monitoring.md ├── go.mod ├── go.sum ├── go.work ├── go.work.sum ├── hack/ │ ├── boilerplate.go.txt │ ├── ci-common.sh │ ├── ci-e2e-kind.sh │ ├── config/ │ │ ├── README.md │ │ ├── cert-manager/ │ │ │ ├── kustomization.yaml │ │ │ ├── patch-mutatingwebhook.yaml │ │ │ ├── patch-validatingwebhook.yaml │ │ │ └── resources/ │ │ │ ├── cluster-issuer.yaml │ │ │ └── kustomization.yaml │ │ ├── certificates/ │ │ │ └── host/ │ │ │ ├── config.json │ │ │ ├── generate.sh │ │ │ ├── kustomization.yaml │ │ │ ├── webhook-ca-key.pem │ │ │ ├── webhook-ca.json │ │ │ ├── webhook-ca.pem │ │ │ ├── webhook-server-key.pem │ │ │ ├── webhook-server.json │ │ │ └── webhook-server.pem │ │ ├── checksum-controller/ │ │ │ ├── controller/ │ │ │ │ ├── deployment.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── rbac.yaml │ │ │ │ └── serviceaccount.yaml │ │ │ └── controllerring/ │ │ │ ├── controllerring.yaml │ │ │ ├── kustomization.yaml │ │ │ └── sharder_rbac.yaml │ │ ├── external-dns/ │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── patch-deployment.yaml │ │ ├── ingress-nginx/ │ │ │ ├── default/ │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── patch_controller_resources.yaml │ │ │ │ └── patch_default_ingress_class.yaml │ │ │ ├── kind/ │ │ │ │ ├── kustomization.yaml │ │ │ │ └── patch_service_nodeport.yaml │ │ │ └── shoot/ │ │ │ ├── certificate.yaml │ │ │ ├── kustomization.yaml │ │ │ └── patch_service.yaml │ │ ├── kind-config.yaml │ │ ├── kyverno/ │ │ │ └── kustomization.yaml │ │ ├── monitoring/ │ │ │ ├── crds/ │ │ │ │ ├── 0alertmanagerConfigCustomResourceDefinition.yaml │ │ │ │ ├── 0alertmanagerCustomResourceDefinition.yaml │ │ │ │ ├── 0podmonitorCustomResourceDefinition.yaml │ │ │ │ ├── 0probeCustomResourceDefinition.yaml │ │ │ │ ├── 0prometheusCustomResourceDefinition.yaml │ │ │ │ ├── 0prometheusagentCustomResourceDefinition.yaml │ │ │ │ ├── 0prometheusruleCustomResourceDefinition.yaml │ │ │ │ ├── 0scrapeconfigCustomResourceDefinition.yaml │ │ │ │ ├── 0servicemonitorCustomResourceDefinition.yaml │ │ │ │ ├── 0thanosrulerCustomResourceDefinition.yaml │ │ │ │ ├── README.md │ │ │ │ └── kustomization.yaml │ │ │ ├── default/ │ │ │ │ ├── dashboards/ │ │ │ │ │ ├── client-go.json │ │ │ │ │ ├── controller-details.json │ │ │ │ │ └── controller-runtime.json │ │ │ │ ├── ensure-admin-password.sh │ │ │ │ ├── grafana_ingress.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── namespace.yaml │ │ │ │ ├── patch_grafana_admin.yaml │ │ │ │ ├── patch_grafana_networkpolicy.yaml │ │ │ │ ├── patch_kubelet_metrics.yaml │ │ │ │ ├── patch_kubestatemetrics.yaml │ │ │ │ ├── patch_kubestatemetrics_servicemonitor.yaml │ │ │ │ ├── patch_prometheus.yaml │ │ │ │ └── rbac-proxy_clusterrole.yaml │ │ │ ├── grafana-sidecar/ │ │ │ │ ├── dashboards-sidecar.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── patch_grafana_sidecar.yaml │ │ │ │ ├── sidecar_clusterrole.yaml │ │ │ │ └── sidecar_clusterrolebinding.yaml │ │ │ ├── kube-prometheus/ │ │ │ │ ├── README.md │ │ │ │ ├── blackboxExporter-clusterRole.yaml │ │ │ │ ├── blackboxExporter-clusterRoleBinding.yaml │ │ │ │ ├── blackboxExporter-configuration.yaml │ │ │ │ ├── blackboxExporter-deployment.yaml │ │ │ │ ├── blackboxExporter-networkPolicy.yaml │ │ │ │ ├── blackboxExporter-service.yaml │ │ │ │ ├── blackboxExporter-serviceAccount.yaml │ │ │ │ ├── blackboxExporter-serviceMonitor.yaml │ │ │ │ ├── grafana-config.yaml │ │ │ │ ├── grafana-dashboardDatasources.yaml │ │ │ │ ├── grafana-dashboardDefinitions.yaml │ │ │ │ ├── grafana-dashboardSources.yaml │ │ │ │ ├── grafana-deployment.yaml │ │ │ │ ├── grafana-networkPolicy.yaml │ │ │ │ ├── grafana-prometheusRule.yaml │ │ │ │ ├── grafana-service.yaml │ │ │ │ ├── grafana-serviceAccount.yaml │ │ │ │ ├── grafana-serviceMonitor.yaml │ │ │ │ ├── kubePrometheus-prometheusRule.yaml │ │ │ │ ├── kubeStateMetrics-clusterRole.yaml │ │ │ │ ├── kubeStateMetrics-clusterRoleBinding.yaml │ │ │ │ ├── kubeStateMetrics-deployment.yaml │ │ │ │ ├── kubeStateMetrics-networkPolicy.yaml │ │ │ │ ├── kubeStateMetrics-prometheusRule.yaml │ │ │ │ ├── kubeStateMetrics-service.yaml │ │ │ │ ├── kubeStateMetrics-serviceAccount.yaml │ │ │ │ ├── kubeStateMetrics-serviceMonitor.yaml │ │ │ │ ├── kubernetesControlPlane-prometheusRule.yaml │ │ │ │ ├── kubernetesControlPlane-serviceMonitorApiserver.yaml │ │ │ │ ├── kubernetesControlPlane-serviceMonitorCoreDNS.yaml │ │ │ │ ├── kubernetesControlPlane-serviceMonitorKubeControllerManager.yaml │ │ │ │ ├── kubernetesControlPlane-serviceMonitorKubeScheduler.yaml │ │ │ │ ├── kubernetesControlPlane-serviceMonitorKubelet.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── nodeExporter-clusterRole.yaml │ │ │ │ ├── nodeExporter-clusterRoleBinding.yaml │ │ │ │ ├── nodeExporter-daemonset.yaml │ │ │ │ ├── nodeExporter-networkPolicy.yaml │ │ │ │ ├── nodeExporter-prometheusRule.yaml │ │ │ │ ├── nodeExporter-service.yaml │ │ │ │ ├── nodeExporter-serviceAccount.yaml │ │ │ │ ├── nodeExporter-serviceMonitor.yaml │ │ │ │ ├── prometheus-clusterRole.yaml │ │ │ │ ├── prometheus-clusterRoleBinding.yaml │ │ │ │ ├── prometheus-networkPolicy.yaml │ │ │ │ ├── prometheus-prometheus.yaml │ │ │ │ ├── prometheus-prometheusRule.yaml │ │ │ │ ├── prometheus-roleBindingConfig.yaml │ │ │ │ ├── prometheus-roleBindingSpecificNamespaces.yaml │ │ │ │ ├── prometheus-roleConfig.yaml │ │ │ │ ├── prometheus-roleSpecificNamespaces.yaml │ │ │ │ ├── prometheus-service.yaml │ │ │ │ ├── prometheus-serviceAccount.yaml │ │ │ │ ├── prometheus-serviceMonitor.yaml │ │ │ │ ├── prometheusAdapter-clusterRole.yaml │ │ │ │ ├── prometheusAdapter-clusterRoleAggregatedMetricsReader.yaml │ │ │ │ ├── prometheusAdapter-clusterRoleBinding.yaml │ │ │ │ ├── prometheusAdapter-clusterRoleBindingDelegator.yaml │ │ │ │ ├── prometheusAdapter-clusterRoleServerResources.yaml │ │ │ │ ├── prometheusAdapter-configMap.yaml │ │ │ │ ├── prometheusAdapter-deployment.yaml │ │ │ │ ├── prometheusAdapter-networkPolicy.yaml │ │ │ │ ├── prometheusAdapter-podDisruptionBudget.yaml │ │ │ │ ├── prometheusAdapter-roleBindingAuthReader.yaml │ │ │ │ ├── prometheusAdapter-service.yaml │ │ │ │ ├── prometheusAdapter-serviceAccount.yaml │ │ │ │ ├── prometheusAdapter-serviceMonitor.yaml │ │ │ │ ├── prometheusOperator-clusterRole.yaml │ │ │ │ ├── prometheusOperator-clusterRoleBinding.yaml │ │ │ │ ├── prometheusOperator-deployment.yaml │ │ │ │ ├── prometheusOperator-networkPolicy.yaml │ │ │ │ ├── prometheusOperator-prometheusRule.yaml │ │ │ │ ├── prometheusOperator-service.yaml │ │ │ │ ├── prometheusOperator-serviceAccount.yaml │ │ │ │ └── prometheusOperator-serviceMonitor.yaml │ │ │ ├── shoot/ │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── patch_prometheus.yaml │ │ │ │ └── storageclass.yaml │ │ │ └── update.sh │ │ ├── policy/ │ │ │ ├── ci/ │ │ │ │ ├── kustomization.yaml │ │ │ │ └── no-requests.yaml │ │ │ ├── controlplane/ │ │ │ │ ├── etcd-main.yaml │ │ │ │ ├── kube-apiserver.yaml │ │ │ │ ├── kube-controller-manager.yaml │ │ │ │ └── kustomization.yaml │ │ │ └── shoot/ │ │ │ ├── kustomization.yaml │ │ │ └── sharder-scheduling.yaml │ │ ├── profiling/ │ │ │ ├── ensure-admin-password.sh │ │ │ ├── kustomization.yaml │ │ │ ├── parca_config.yaml │ │ │ ├── parca_ingress.yaml │ │ │ ├── parca_pvc.yaml │ │ │ ├── patch_deployment_pvc.yaml │ │ │ └── rbac_sharder.yaml │ │ ├── sharder/ │ │ │ ├── devel/ │ │ │ │ └── kustomization.yaml │ │ │ └── host/ │ │ │ └── config.yaml │ │ ├── shoot.yaml │ │ └── skaffold.yaml │ ├── prepare-image-metadata.sh │ ├── test-e2e.env │ ├── test-e2e.sh │ ├── test-integration.env │ ├── test-integration.sh │ ├── test.sh │ ├── tools.go │ ├── tools.mk │ ├── update-codegen.sh │ └── vgopath-setup.sh ├── pkg/ │ ├── apis/ │ │ ├── config/ │ │ │ ├── doc.go │ │ │ └── v1alpha1/ │ │ │ ├── defaults.go │ │ │ ├── defaults_test.go │ │ │ ├── doc.go │ │ │ ├── register.go │ │ │ ├── types.go │ │ │ ├── v1alpha1_suite_test.go │ │ │ ├── zz_generated.deepcopy.go │ │ │ └── zz_generated.defaults.go │ │ └── sharding/ │ │ ├── doc.go │ │ └── v1alpha1/ │ │ ├── constants.go │ │ ├── constants_test.go │ │ ├── doc.go │ │ ├── register.go │ │ ├── types_controllerring.go │ │ ├── types_controllerring_test.go │ │ ├── v1alpha1_suite_test.go │ │ └── zz_generated.deepcopy.go │ ├── controller/ │ │ ├── add.go │ │ ├── controllerring/ │ │ │ ├── add.go │ │ │ ├── add_test.go │ │ │ ├── controllerring_suite_test.go │ │ │ ├── reconciler.go │ │ │ └── reconciler_test.go │ │ ├── sharder/ │ │ │ ├── add.go │ │ │ ├── reconciler.go │ │ │ ├── reconciler_test.go │ │ │ └── sharder_suite_test.go │ │ └── shardlease/ │ │ ├── add.go │ │ ├── add_test.go │ │ ├── reconciler.go │ │ └── shardlease_suite_test.go │ ├── metrics/ │ │ ├── add.go │ │ ├── controllerring.go │ │ ├── exporter/ │ │ │ └── exporter.go │ │ ├── operations.go │ │ └── shard.go │ ├── shard/ │ │ ├── controller/ │ │ │ ├── builder.go │ │ │ ├── builder_test.go │ │ │ ├── controller_suite_test.go │ │ │ ├── predicate.go │ │ │ ├── predicate_test.go │ │ │ ├── reconciler.go │ │ │ └── reconciler_test.go │ │ └── lease/ │ │ ├── lease.go │ │ ├── lease_suite_test.go │ │ └── lease_test.go │ ├── sharding/ │ │ ├── consistenthash/ │ │ │ ├── benchmark_test.go │ │ │ ├── consistenthash_suite_test.go │ │ │ ├── ring.go │ │ │ └── ring_test.go │ │ ├── handler/ │ │ │ ├── controllerring.go │ │ │ ├── controllerring_test.go │ │ │ ├── handler_suite_test.go │ │ │ ├── lease.go │ │ │ └── lease_test.go │ │ ├── key/ │ │ │ ├── key.go │ │ │ ├── key_suite_test.go │ │ │ └── key_test.go │ │ ├── leases/ │ │ │ ├── leases_suite_test.go │ │ │ ├── shards.go │ │ │ ├── shards_test.go │ │ │ ├── state.go │ │ │ ├── state_test.go │ │ │ ├── times.go │ │ │ └── times_test.go │ │ ├── predicate/ │ │ │ ├── controllerring.go │ │ │ ├── controllerring_test.go │ │ │ ├── lease.go │ │ │ ├── lease_test.go │ │ │ └── predicate_suite_test.go │ │ └── ring/ │ │ ├── ring.go │ │ ├── ring_suite_test.go │ │ └── ring_test.go │ ├── utils/ │ │ ├── client/ │ │ │ ├── client_suite_test.go │ │ │ ├── options.go │ │ │ ├── options_test.go │ │ │ └── scheme.go │ │ ├── errors/ │ │ │ ├── errors_suite_test.go │ │ │ ├── multi.go │ │ │ └── multi_test.go │ │ ├── healthz/ │ │ │ ├── cache.go │ │ │ ├── cache_test.go │ │ │ └── healthz_suite_test.go │ │ ├── pager/ │ │ │ ├── pager.go │ │ │ ├── pager_suite_test.go │ │ │ └── pager_test.go │ │ ├── routes/ │ │ │ └── profiling.go │ │ ├── strings.go │ │ ├── strings_test.go │ │ ├── test/ │ │ │ ├── envtest.go │ │ │ ├── matchers/ │ │ │ │ ├── condition.go │ │ │ │ ├── errors.go │ │ │ │ ├── matchers.go │ │ │ │ └── object.go │ │ │ ├── object.go │ │ │ └── paths.go │ │ └── utils_suite_test.go │ └── webhook/ │ ├── add.go │ └── sharder/ │ ├── add.go │ ├── add_test.go │ ├── handler.go │ ├── handler_test.go │ ├── metrics.go │ └── sharder_suite_test.go ├── test/ │ ├── e2e/ │ │ ├── checksum_controller_test.go │ │ └── e2e_suite_test.go │ └── integration/ │ ├── shard/ │ │ ├── controller/ │ │ │ ├── controller_suite_test.go │ │ │ ├── controller_test.go │ │ │ └── reconciler.go │ │ └── lease/ │ │ ├── lease_suite_test.go │ │ └── lease_test.go │ └── sharder/ │ ├── controller/ │ │ ├── controllerring/ │ │ │ ├── controllerring_suite_test.go │ │ │ └── controllerring_test.go │ │ ├── sharder/ │ │ │ ├── sharder_suite_test.go │ │ │ └── sharder_test.go │ │ └── shardlease/ │ │ ├── shardlease_suite_test.go │ │ └── shardlease_test.go │ └── webhook/ │ └── sharder/ │ ├── sharder_suite_test.go │ └── sharder_test.go └── webhosting-operator/ ├── PROJECT ├── README.md ├── cmd/ │ ├── experiment/ │ │ └── main.go │ ├── measure/ │ │ ├── main.go │ │ └── test.yaml │ ├── samples-generator/ │ │ └── main.go │ └── webhosting-operator/ │ └── main.go ├── config/ │ ├── experiment/ │ │ ├── base/ │ │ │ ├── job.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ ├── prometheus_rbac.yaml │ │ │ ├── rbac.yaml │ │ │ ├── service.yaml │ │ │ └── servicemonitor.yaml │ │ ├── basic/ │ │ │ └── kustomization.yaml │ │ ├── chaos/ │ │ │ └── kustomization.yaml │ │ ├── rolling-update/ │ │ │ └── kustomization.yaml │ │ └── scale-out/ │ │ └── kustomization.yaml │ ├── manager/ │ │ ├── base/ │ │ │ ├── kustomization.yaml │ │ │ ├── manager.yaml │ │ │ ├── metrics_auth.yaml │ │ │ ├── namespace.yaml │ │ │ └── service.yaml │ │ ├── controllerring/ │ │ │ ├── controllerring.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── manager_patch.yaml │ │ │ └── sharder_rbac.yaml │ │ ├── crds/ │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ ├── webhosting.timebertt.dev_themes.yaml │ │ │ └── webhosting.timebertt.dev_websites.yaml │ │ ├── devel/ │ │ │ └── kustomization.yaml │ │ ├── overlays/ │ │ │ ├── debug/ │ │ │ │ ├── kustomization.yaml │ │ │ │ └── manager_debug_patch.yaml │ │ │ ├── default/ │ │ │ │ └── kustomization.yaml │ │ │ ├── devel/ │ │ │ │ └── kustomization.yaml │ │ │ ├── non-sharded/ │ │ │ │ ├── kustomization.yaml │ │ │ │ └── manager_patch.yaml │ │ │ ├── non-sharded-devel/ │ │ │ │ └── kustomization.yaml │ │ │ └── shoot/ │ │ │ ├── default/ │ │ │ │ └── kustomization.yaml │ │ │ ├── devel/ │ │ │ │ └── kustomization.yaml │ │ │ ├── non-sharded/ │ │ │ │ └── kustomization.yaml │ │ │ └── non-sharded-devel/ │ │ │ └── kustomization.yaml │ │ ├── rbac/ │ │ │ ├── kustomization.yaml │ │ │ ├── leader_election_role.yaml │ │ │ ├── leader_election_role_binding.yaml │ │ │ ├── parca_rbac.yaml │ │ │ ├── role.yaml │ │ │ ├── role_binding.yaml │ │ │ ├── service_account.yaml │ │ │ ├── theme_editor_role.yaml │ │ │ ├── theme_viewer_role.yaml │ │ │ ├── website_editor_role.yaml │ │ │ └── website_viewer_role.yaml │ │ └── with-dns/ │ │ ├── config.yaml │ │ ├── kustomization.yaml │ │ └── manager_patch.yaml │ ├── monitoring/ │ │ ├── default/ │ │ │ ├── dashboards/ │ │ │ │ ├── experiments.json │ │ │ │ ├── sharding.json │ │ │ │ └── webhosting.json │ │ │ └── kustomization.yaml │ │ └── webhosting-operator/ │ │ ├── kustomization.yaml │ │ ├── prometheus_rbac.yaml │ │ ├── prometheusrule.yaml │ │ └── servicemonitor.yaml │ ├── policy/ │ │ ├── experiment-scheduling.yaml │ │ ├── guaranteed-resources.yaml │ │ ├── kustomization.yaml │ │ ├── scale-up-worker-experiment.yaml │ │ └── webhosting-operator-scheduling.yaml │ └── samples/ │ ├── kustomization.yaml │ ├── project_namespace.yaml │ ├── theme_exciting.yaml │ ├── theme_lame.yaml │ ├── website_kubecon.yaml │ ├── website_library.yaml │ └── website_museum.yaml ├── go.mod ├── go.sum ├── pkg/ │ ├── apis/ │ │ ├── config/ │ │ │ ├── doc.go │ │ │ └── v1alpha1/ │ │ │ ├── defaults.go │ │ │ ├── doc.go │ │ │ ├── register.go │ │ │ ├── types.go │ │ │ ├── zz_generated.deepcopy.go │ │ │ └── zz_generated.defaults.go │ │ └── webhosting/ │ │ ├── doc.go │ │ └── v1alpha1/ │ │ ├── constants.go │ │ ├── doc.go │ │ ├── register.go │ │ ├── types_theme.go │ │ ├── types_website.go │ │ └── zz_generated.deepcopy.go │ ├── controllers/ │ │ └── webhosting/ │ │ ├── suite_test.go │ │ ├── templates/ │ │ │ ├── index.go │ │ │ ├── index.tmpl │ │ │ ├── index_test.go │ │ │ ├── internal/ │ │ │ │ └── examples.go │ │ │ ├── nginx.conf.tmpl │ │ │ ├── nginx.go │ │ │ ├── nginx_test.go │ │ │ ├── templates_suite_test.go │ │ │ └── testserver/ │ │ │ └── server.go │ │ └── website_controller.go │ ├── experiment/ │ │ ├── generator/ │ │ │ ├── options.go │ │ │ ├── project.go │ │ │ ├── reconciler.go │ │ │ ├── theme.go │ │ │ ├── utils.go │ │ │ └── website.go │ │ ├── scenario/ │ │ │ ├── all/ │ │ │ │ └── all.go │ │ │ ├── base/ │ │ │ │ └── base.go │ │ │ ├── basic/ │ │ │ │ └── basic.go │ │ │ ├── chaos/ │ │ │ │ └── chaos.go │ │ │ ├── rolling-update/ │ │ │ │ └── rolling_update.go │ │ │ └── scale-out/ │ │ │ └── scale_out.go │ │ ├── scenario.go │ │ └── tracker/ │ │ ├── tracker.go │ │ └── website.go │ ├── metrics/ │ │ ├── add.go │ │ ├── theme.go │ │ └── website.go │ └── utils/ │ ├── kubernetes.go │ └── utils.go └── test/ └── e2e/ ├── e2e_suite_test.go └── webhosting_operator_test.go ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ docs/assets/*.jpg filter=lfs diff=lfs merge=lfs -text ================================================ FILE: .github/ISSUE_TEMPLATE/bug.md ================================================ --- name: Bug Report about: Report a bug encountered while using this project labels: bug --- **What happened**: **What you expected to happen**: **How to reproduce it (as minimally and precisely as possible)**: **Anything else we need to know?**: **Environment**: - kubernetes-controller-sharding version: - Kubernetes version: - Others: ================================================ FILE: .github/ISSUE_TEMPLATE/enhancement.md ================================================ --- name: Enhancement Request about: Suggest an enhancement to this project labels: enhancement --- **What would you like to be added**: **Why is this needed**: ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ **What this PR does / why we need it**: **Which issue(s) this PR fixes**: Fixes # **Special notes for your reviewer**: ================================================ FILE: .github/release.yaml ================================================ changelog: exclude: labels: - no-release-note categories: - title: ⚠️ Breaking Changes labels: - breaking - title: ✨ Features labels: - enhancement - title: 🐛 Bug Fixes labels: - bug - title: 📖 Documentation labels: - documentation - title: 🧹 Cleanups labels: - cleanup - title: 🤖 Dependencies labels: - dependencies - title: ℹ️ Other Changes labels: - "*" ================================================ FILE: .github/renovate.json5 ================================================ { $schema: 'https://docs.renovatebot.com/renovate-schema.json', extends: [ 'config:recommended', ':semanticCommitsDisabled', 'customManagers:githubActionsVersions', ], labels: [ 'dependencies', ], postUpdateOptions: [ 'gomodTidy', ], automergeStrategy: 'squash', // required for automerging patch updates separateMinorPatch: true, kubernetes: { managerFilePatterns: [ '/\\.yaml$/', ], }, customManagers: [ { // generic detection for install manifests from GitHub releases customType: 'regex', managerFilePatterns: [ '/kustomization\\.yaml$/', ], matchStrings: [ 'https://github\\.com/(?.*/.*?)/releases/download/(?.*?)/', ], datasourceTemplate: 'github-releases', }, { // generic detection for raw manifests from GitHub refs customType: 'regex', managerFilePatterns: [ '/kustomization\\.yaml$/', ], matchStrings: [ 'https://raw.githubusercontent.com/(?.*?/.*?)/(?.*?)/', ], datasourceTemplate: 'github-releases', }, { // update `_VERSION` variables in Makefiles and scripts // inspired by `regexManagers:dockerfileVersions` preset customType: 'regex', managerFilePatterns: [ '/Makefile$/', '/\\.mk$/', '/\\.sh$/', ], matchStrings: [ '# renovate: datasource=(?[a-z-.]+?) depName=(?[^\\s]+?)(?: (lookupName|packageName)=(?[^\\s]+?))?(?: versioning=(?[^\\s]+?))?(?: extractVersion=(?[^\\s]+?))?(?: registryUrl=(?[^\\s]+?))?\\s.+?_VERSION *[?:]?= *"?(?.+?)"?\\s', ], }, { // custom manager for updating kind node image tag and digest customType: "regex", managerFilePatterns: [ "/^Makefile$/", ], matchStrings: [ "(?kindest/node):(?[^@]+)(?:@(?[^\\s]+))?", ], datasourceTemplate: "docker", } ], packageRules: [ { // disable update of dependency on the main module matchPackageNames: [ 'github.com/timebertt/kubernetes-controller-sharding', ], enabled: false, }, { // automerge non-major updates except 0.* versions // similar to :automergeStableNonMajor preset, but also works for versioning schemes without range support matchUpdateTypes: [ 'minor', 'patch', ], matchCurrentVersion: '!/^v?0\\./', automerge: true, }, { // automerge patch updates matchUpdateTypes: [ 'patch', ], automerge: true, }, { // automerge non-major golang.org/x updates matchDatasources: [ 'go', ], matchPackageNames: [ 'golang.org/x/*', ], matchUpdateTypes: [ 'minor', 'patch', 'digest', ], automerge: true, }, { // disable automerge for go minor updates matchDatasources: [ 'golang-version', ], matchUpdateTypes: [ 'minor', ], automerge: false, }, { // bump k8s and controller-runtime go dependencies together groupName: 'k8s packages', groupSlug: 'k8s-go', matchDatasources: [ 'go', ], matchPackageNames: [ // from "group:kubernetes" 'k8s.io/api', 'k8s.io/apiextensions-apiserver', 'k8s.io/apimachinery', 'k8s.io/apiserver', 'k8s.io/cli-runtime', 'k8s.io/client-go', 'k8s.io/cloud-provider', 'k8s.io/cluster-bootstrap', 'k8s.io/code-generator', 'k8s.io/component-base', 'k8s.io/controller-manager', 'k8s.io/cri-api', 'k8s.io/csi-translation-lib', 'k8s.io/kube-aggregator', 'k8s.io/kube-controller-manager', 'k8s.io/kube-proxy', 'k8s.io/kube-scheduler', 'k8s.io/kubectl', 'k8s.io/kubelet', 'k8s.io/legacy-cloud-providers', 'k8s.io/metrics', 'k8s.io/mount-utils', 'k8s.io/pod-security-admission', 'k8s.io/sample-apiserver', 'k8s.io/sample-cli-plugin', 'k8s.io/sample-controller', // added packages 'sigs.k8s.io/controller-runtime', ], }, { // disable automerge for k8s minor updates matchPackageNames: [ // datasource=go 'k8s.io/**', // includes more than the k8s-go group! (e.g., k8s.io/utils) 'sigs.k8s.io/controller-runtime', // datasource=github-releases 'kubernetes/kubernetes', 'kubernetes-sigs/controller-tools', ], matchUpdateTypes: [ 'minor', ], automerge: false, }, { // automerge k8s.io/utils updates matchDatasources: [ 'go', ], matchPackageNames: [ 'k8s.io/utils', ], matchUpdateTypes: [ 'digest', ], automerge: true, }, { // jsonpatch major version has to be kept in sync with k8s and controller-runtime dependencies matchDatasources: [ 'go', ], matchPackageNames: [ 'gomodules.xyz/jsonpatch/*', ], matchUpdateTypes: [ 'major', ], enabled: false, }, { // kind minor k8s version should be updated together with shoot k8s version matchPackageNames: [ 'kindest/node', ], matchUpdateTypes: [ 'minor', ], enabled: false, }, // don't add internal dependency updates to release notes { matchFileNames: [ 'hack/config/**', 'hack/tools.mk', ], matchPackageNames: [ '!kubernetes-sigs/controller-tools', '!ko-build/ko', ], addLabels: [ 'no-release-note', ], }, { matchDatasources: [ 'go', ], matchPackageNames: [ 'github.com/onsi/gomega', 'github.com/onsi/ginkgo/*', 'k8s.io/utils', ], addLabels: [ 'no-release-note', ], }, { // combine upgrade of manifests and image tag in one PR groupName: 'external-dns', matchPackageNames: [ '/external-dns/', ], }, { // special case for ingress-nginx: version is prefixed with `controller-` matchDatasources: [ 'github-releases', ], matchPackageNames: [ 'kubernetes/ingress-nginx', ], versionCompatibility: '^(?.*)-(?.+)$', }, { // manual action required: upgrading kube-prometheus is not fully automated yet matchDatasources: [ 'github-releases', ], matchPackageNames: [ 'prometheus-operator/kube-prometheus', ], prHeader: '⚠️ Manual action required ⚠️\nPlease check this PR out and run `hack/config/monitoring/update.sh`.', }, { // kube-prometheus manifests are generated and managed by update.sh, disable renovate bumps matchFileNames: [ 'hack/config/monitoring/{crds,kube-prometheus}/**', ], enabled: false, }, // help renovate fetch changelogs for packages that don't have any sourceUrl metadata attached { matchPackageNames: [ 'registry.k8s.io/prometheus-adapter/prometheus-adapter', ], changelogUrl: 'https://github.com/kubernetes-sigs/prometheus-adapter', }, { matchPackageNames: [ 'quay.io/brancz/kube-rbac-proxy', ], changelogUrl: 'https://github.com/brancz/kube-rbac-proxy', }, ], } ================================================ FILE: .github/workflows/e2e.yaml ================================================ name: e2e on: push: branches: - main tags: - v* paths-ignore: - "**.md" pull_request: jobs: e2e-kind: runs-on: ubuntu-latest env: ARTIFACTS: artifacts steps: - uses: actions/checkout@v5 - uses: actions/setup-go@v6 with: go-version-file: go.mod - run: make ci-e2e-kind - uses: actions/upload-artifact@v5 if: always() with: name: e2e-artifacts path: artifacts if-no-files-found: error ================================================ FILE: .github/workflows/images.yaml ================================================ name: images on: push: branches: - main tags: - v* pull_request: jobs: images: runs-on: ubuntu-latest env: # renovate: datasource=github-releases depName=ko-build/ko KO_VERSION: v0.18.1 steps: - uses: actions/checkout@v5 with: # fetch all history so that git describe works (needed by hack/prepare-image-metadata.sh) fetch-depth: 0 - uses: actions/setup-go@v6 with: go-version-file: go.mod - uses: ko-build/setup-ko@v0.9 with: version: ${{ env.KO_VERSION }} - name: Prepare image metadata id: meta run: ./hack/prepare-image-metadata.sh - name: ko build run: | set -ex # prepare .ko.yaml to inject build settings into all images entrypoints=( ./cmd/sharder ./cmd/checksum-controller ./webhosting-operator/cmd/experiment ./webhosting-operator/cmd/webhosting-operator ) echo builds: > .ko.yaml for entrypoint in "${entrypoints[@]}" ; do cat >> .ko.yaml </dev/null ; then echo "Skipping renovate post update workflow" echo "skip=true" >> $GITHUB_OUTPUT fi # Some dependency updates might require updating go.work.sum. # Automatically run `make tidy` on renovate branches as long as renovate doesn't know how to handle go workspaces. # Some dependency updates might require re-running code generation. # Run `make generate` and commit all changes if any. - run: make tidy generate if: steps.safety.outputs.skip != 'true' - uses: stefanzweifel/git-auto-commit-action@v7 if: steps.safety.outputs.skip != 'true' with: commit_message: | make tidy generate [skip renovate-post-update] # commit with renovate's user, so that it doesn't block further updates to the PR commit_user_name: renovate[bot] commit_user_email: 29139614+renovate[bot]@users.noreply.github.com commit_author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> ================================================ FILE: .github/workflows/verify.yaml ================================================ name: verify on: push: branches: - main tags: - v* pull_request: jobs: verify: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - uses: actions/setup-go@v6 with: go-version-file: go.mod - run: make verify ================================================ FILE: .gitignore ================================================ *.secret* .envrc hack/kind_kubeconfig.yaml .gitguardian.yaml .ko.yaml # Binaries for programs and plugins *.exe *.exe~ *.dll *.so *.dylib bin testbin/* # Test binary, build with `go test -c` *.test # Output of the go coverage tool, specifically when used with LiteIDE *.out # editor and IDE settings .idea .vscode *.swp *.swo *~ ================================================ FILE: .golangci.yaml ================================================ version: "2" run: concurrency: 4 linters: enable: - copyloopvar - ginkgolinter - gocritic - gosec - importas - misspell - nilerr - nolintlint - prealloc - revive - staticcheck - unconvert - unparam - whitespace settings: importas: alias: - pkg: github.com/timebertt/kubernetes-controller-sharding/apis/(\w+)/(v[\w\d]+) alias: $1$2 - pkg: github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/apis/(\w+)/(v[\w\d]+) alias: $1$2 - pkg: k8s.io/api/(\w+)/(v[\w\d]+) alias: $1$2 - pkg: k8s.io/apimachinery/pkg/apis/(\w+)/(v[\w\d]+) alias: $1$2 - pkg: k8s.io/apimachinery/pkg/api/([^m]\w+) alias: api${1} - pkg: k8s.io/apimachinery/pkg/util/(\w+) alias: util${1} - pkg: k8s.io/client-go/tools/clientcmd/api/(\w+) alias: clientcmd${1} - pkg: k8s.io/client-go/tools/cache alias: toolscache - pkg: k8s.io/component-base/config/(v[\w\d]+) alias: componentbaseconfig$1 - pkg: k8s.io/utils/clock/testing alias: testclock - pkg: sigs.k8s.io/controller-runtime/pkg/client/fake alias: fakeclient - pkg: sigs.k8s.io/controller-runtime/pkg/log/zap alias: logzap - pkg: sigs.k8s.io/controller-runtime/pkg/log alias: logf misspell: locale: US nolintlint: require-specific: true revive: rules: - name: context-as-argument - name: duplicated-imports - name: early-return - name: exported - name: unreachable-code exclusions: generated: strict presets: - comments - common-false-positives - std-error-handling rules: - linters: - staticcheck path: pkg/utils/test text: 'ST1001: should not use dot imports' - linters: - nolintlint text: should be written without leading space ================================================ FILE: .run/experiment (kind).run.xml ================================================ ================================================ FILE: .run/shard (kind).run.xml ================================================ ================================================ FILE: .run/sharder (kind).run.xml ================================================ ================================================ FILE: .run/webhosting-operator (kind).run.xml ================================================ ================================================ FILE: LICENSE ================================================ 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. ================================================ FILE: Makefile ================================================ PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) # Image URL to use all building/pushing image targets TAG ?= latest GHCR_REPO ?= ghcr.io/timebertt/kubernetes-controller-sharding SHARDER_IMG ?= $(GHCR_REPO)/sharder:$(TAG) CHECKSUM_CONTROLLER_IMG ?= $(GHCR_REPO)/checksum-controller:$(TAG) WEBHOSTING_OPERATOR_IMG ?= $(GHCR_REPO)/webhosting-operator:$(TAG) EXPERIMENT_IMG ?= $(GHCR_REPO)/experiment:$(TAG) # Optionally, overwrite the envtest version or assets directory to use ENVTEST_K8S_VERSION = KUBEBUILDER_ASSETS = # Setting SHELL to bash allows bash commands to be executed by recipes. # Options are set to exit when a recipe line exits non-zero or a piped command fails. SHELL = /usr/bin/env bash -o pipefail .SHELLFLAGS = -ec .PHONY: all all: build ##@ General # The help target prints out all targets with their descriptions organized # beneath their categories. The categories are represented by '##@' and the # target descriptions by '##'. The awk commands is responsible for reading the # entire set of makefiles included in this invocation, looking for lines of the # file as xyz: ## something, and then pretty-format the target and help. Then, # if there's a line with ##@ something, that gets pretty-printed as a category. # More info on the usage of ANSI control characters for terminal formatting: # https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters # More info on the awk command: # http://linuxcommand.org/lc3_adv_awk.php .PHONY: help help: ## Display this help. @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) ##@ Tools include hack/tools.mk .PHONY: clean-tools-bin clean-tools-bin: ## Empty the tools binary directory. rm -rf $(TOOLS_BIN_DIR)/* ##@ Development .PHONY: tidy tidy: ## Runs go mod to ensure modules are up to date. go mod tidy cd webhosting-operator && go mod tidy @# regenerate go.work.sum rm -f go.work.sum go mod download .PHONY: generate-fast generate-fast: $(CONTROLLER_GEN) tidy ## Run all fast code generators for the main module. $(CONTROLLER_GEN) rbac:roleName=sharder crd paths="./pkg/..." output:rbac:artifacts:config=config/rbac output:crd:artifacts:config=config/crds $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./pkg/..." .PHONY: generate-fast-webhosting generate-fast-webhosting: $(CONTROLLER_GEN) tidy ## Run all fast code generators for the webhosting-operator module. $(CONTROLLER_GEN) rbac:roleName=operator crd paths="./webhosting-operator/..." output:rbac:artifacts:config=webhosting-operator/config/manager/rbac output:crd:artifacts:config=webhosting-operator/config/manager/crds $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./webhosting-operator/..." .PHONY: generate generate: $(VGOPATH) generate-fast generate-fast-webhosting tidy ## Run all code generators. hack/update-codegen.sh .PHONY: fmt fmt: ## Run go fmt against code. go fmt ./... cd webhosting-operator && go fmt ./... .PHONY: test test: ## Run unit tests. ./hack/test.sh ./cmd/... ./pkg/... ./webhosting-operator/pkg/... .PHONY: test-integration test-integration: $(SETUP_ENVTEST) ## Run integration tests. ./hack/test-integration.sh ./test/integration/... .PHONY: test-e2e test-e2e: $(GINKGO) ## Run e2e tests. ./hack/test-e2e.sh $(GINKGO_FLAGS) ./test/e2e/... ./webhosting-operator/test/e2e/... .PHONY: skaffold-fix skaffold-fix: $(SKAFFOLD) ## Upgrade skaffold configuration to the latest apiVersion. $(SKAFFOLD) fix --overwrite [ ! -f $(SKAFFOLD_FILENAME).v2 ] || rm $(SKAFFOLD_FILENAME).v2 ##@ Verification .PHONY: lint lint: $(GOLANGCI_LINT) ## Run golangci-lint against code. $(GOLANGCI_LINT) run ./... ./webhosting-operator/... .PHONY: check check: lint test test-integration ## Check everything (lint + test + test-integration). .PHONY: verify-fmt verify-fmt: fmt ## Verify go code is formatted. @if !(git diff --quiet HEAD); then \ echo "unformatted files detected, please run 'make fmt'"; exit 1; \ fi .PHONY: verify-generate verify-generate: generate ## Verify generated files are up to date. @if !(git diff --quiet HEAD); then \ echo "generated files are out of date, please run 'make generate'"; exit 1; \ fi .PHONY: verify-tidy verify-tidy: tidy ## Verify go module files are up to date. @if !(git diff --quiet HEAD -- go.work.sum go.{mod,sum} webhosting-operator/go.{mod,sum}); then \ echo "go module files are out of date, please run 'make tidy'"; exit 1; \ fi .PHONY: verify verify: verify-tidy verify-fmt verify-generate check ## Verify everything (all verify-* rules + check). .PHONY: ci-e2e-kind ci-e2e-kind: $(KIND) ./hack/ci-e2e-kind.sh ##@ Build .PHONY: build build: ## Build the sharder binary. go build -o bin/sharder ./cmd/sharder .PHONY: run run: $(KUBECTL) generate-fast ## Run the sharder from your host and deploy prerequisites. $(MAKE) deploy SKAFFOLD_MODULE=cert-manager $(KUBECTL) apply --server-side --force-conflicts -k config/crds $(KUBECTL) apply --server-side --force-conflicts -k hack/config/certificates/host go run ./cmd/sharder --config=hack/config/sharder/host/config.yaml --zap-devel SHARD_NAME ?= checksum-controller-$(shell tr -dc bcdfghjklmnpqrstvwxz2456789 0 { o.restConfig.QPS = clientConnection.QPS } if clientConnection.Burst > 0 { o.restConfig.Burst = int(clientConnection.Burst) } } } func (o *options) applyConfigToManagerOptions() { if leaderElection := o.config.LeaderElection; leaderElection != nil { o.managerOptions.LeaderElection = *leaderElection.LeaderElect o.managerOptions.LeaderElectionResourceLock = leaderElection.ResourceLock o.managerOptions.LeaderElectionID = leaderElection.ResourceName o.managerOptions.LeaderElectionNamespace = leaderElection.ResourceNamespace o.managerOptions.LeaseDuration = ptr.To(leaderElection.LeaseDuration.Duration) o.managerOptions.RenewDeadline = ptr.To(leaderElection.RenewDeadline.Duration) o.managerOptions.RetryPeriod = ptr.To(leaderElection.RetryPeriod.Duration) } o.managerOptions.HealthProbeBindAddress = o.config.Health.BindAddress if o.config.Metrics.BindAddress != "0" { var extraHandlers map[string]http.Handler if *o.config.Debugging.EnableProfiling { extraHandlers = routes.ProfilingHandlers if *o.config.Debugging.EnableContentionProfiling { goruntime.SetBlockProfileRate(1) } } o.managerOptions.Metrics = metricsserver.Options{ SecureServing: true, BindAddress: o.config.Metrics.BindAddress, FilterProvider: filters.WithAuthenticationAndAuthorization, ExtraHandlers: extraHandlers, } } webhookOptions := webhook.Options{} if serverConfig := o.config.Webhook.Server; serverConfig != nil { webhookOptions.CertDir = ptr.Deref(serverConfig.CertDir, "") webhookOptions.CertName = ptr.Deref(serverConfig.CertName, "") webhookOptions.KeyName = ptr.Deref(serverConfig.KeyName, "") } o.managerOptions.WebhookServer = webhook.NewServer(webhookOptions) o.managerOptions.GracefulShutdownTimeout = ptr.To(o.config.GracefulShutdownTimeout.Duration) } func (o *options) applyCacheOptions() { // filter lease cache for shard leases to avoid watching all leases in cluster leaseSelector := labels.NewSelector() { ringRequirement, err := labels.NewRequirement(shardingv1alpha1.LabelControllerRing, selection.Exists, nil) utilruntime.Must(err) leaseSelector.Add(*ringRequirement) } o.managerOptions.Cache = cache.Options{ DefaultTransform: dropUnwantedMetadata, ByObject: map[client.Object]cache.ByObject{ &coordinationv1.Lease{}: { Label: leaseSelector, }, }, } } func (o *options) applyOptionsOverrides() error { var err error // allow overriding leader election via env var for debugging purposes if leaderElectEnv, ok := os.LookupEnv("LEADER_ELECT"); ok { o.managerOptions.LeaderElection, err = strconv.ParseBool(leaderElectEnv) if err != nil { return fmt.Errorf("error parsing LEADER_ELECT env var: %w", err) } } return nil } func dropUnwantedMetadata(i interface{}) (interface{}, error) { obj, ok := i.(client.Object) if !ok { return i, nil } obj.SetManagedFields(nil) annotations := obj.GetAnnotations() delete(annotations, "kubectl.kubernetes.io/last-applied-configuration") obj.SetAnnotations(annotations) return obj, nil } ================================================ FILE: cmd/sharder/main.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package main import ( "fmt" "os" "sigs.k8s.io/controller-runtime/pkg/manager/signals" "github.com/timebertt/kubernetes-controller-sharding/cmd/sharder/app" ) func main() { if err := app.NewCommand().ExecuteContext(signals.SetupSignalHandler()); err != nil { fmt.Println(err) os.Exit(1) } } ================================================ FILE: config/README.md ================================================ # config This directory hosts manifests for deploying the sharding components. Manifests of components for the development setup should be hosted in [`hack/config`](../hack/config) instead. I.e., this directory should only contain manifests that are useful for others wanting to reuse the sharding components in their setup. ================================================ FILE: config/certificate/certificate.yaml ================================================ apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: webhook-server spec: issuerRef: name: selfsigned commonName: sharding:sharder:webhook dnsNames: - sharder.sharding-system - sharder.sharding-system.svc - sharder.sharding-system.svc.cluster.local secretName: webhook-server ================================================ FILE: config/certificate/issuer.yaml ================================================ apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: selfsigned spec: selfSigned: {} ================================================ FILE: config/certificate/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component namespace: sharding-system labels: - includeSelectors: true pairs: app.kubernetes.io/name: controller-sharding resources: - certificate.yaml - issuer.yaml patches: - patch: | apiVersion: apps/v1 kind: Deployment metadata: name: sharder namespace: sharding-system spec: template: spec: containers: - name: sharder volumeMounts: - name: cert mountPath: /tmp/k8s-webhook-server/serving-certs volumes: - name: cert secret: secretName: webhook-server ================================================ FILE: config/crds/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization labels: - includeSelectors: true pairs: app.kubernetes.io/name: controller-sharding resources: - namespace.yaml - sharding.timebertt.dev_controllerrings.yaml ================================================ FILE: config/crds/namespace.yaml ================================================ apiVersion: v1 kind: Namespace metadata: name: sharding-system ================================================ FILE: config/crds/sharding.timebertt.dev_controllerrings.yaml ================================================ --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 name: controllerrings.sharding.timebertt.dev spec: group: sharding.timebertt.dev names: kind: ControllerRing listKind: ControllerRingList plural: controllerrings singular: controllerring scope: Cluster versions: - additionalPrinterColumns: - jsonPath: .status.conditions[?(@.type == "Ready")].status name: Ready type: string - jsonPath: .status.availableShards name: Available type: string - jsonPath: .status.shards name: Shards type: string - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1alpha1 schema: openAPIV3Schema: description: |- ControllerRing declares a virtual ring of sharded controller instances. Objects of the specified resources are distributed across shards of this ring. Objects in all namespaces are considered unless a namespaceSelector is specified. 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 contains the specification of the desired behavior of the ControllerRing. properties: namespaceSelector: description: |- NamespaceSelector overwrites the webhook configs' namespaceSelector. If set, this selector should exclude the kube-system and sharding-system namespaces. If omitted, the default namespaceSelector from the SharderConfig is used. Note: changing/unsetting this selector will not remove labels from objects in namespaces that were previously included. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic resources: description: Resources specifies the list of resources that are distributed across shards in this ControllerRing. items: description: RingResource specifies a resource along with controlled resources that is distributed across shards in a ring. properties: controlledResources: description: |- ControlledResources are additional resources that are distributed across shards in the ControllerRing. These resources are controlled by the controller's main resource, i.e., they have an owner reference with controller=true back to the GroupResource of this RingResource. Typically, the controller also watches objects of this resource and enqueues the owning object (of the main resource) whenever the status of a controlled object changes. items: description: |- GroupResource specifies a Group and a Resource, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types properties: group: type: string resource: type: string required: - group - resource type: object type: array x-kubernetes-list-map-keys: - group - resource x-kubernetes-list-type: map group: type: string resource: type: string required: - group - resource type: object type: array x-kubernetes-list-map-keys: - group - resource x-kubernetes-list-type: map type: object status: description: Status contains the most recently observed status of the ControllerRing. properties: availableShards: description: AvailableShards is the total number of available shards of this ring. format: int32 type: integer conditions: description: |- Conditions represents the observations of a foo's current state. Known .status.conditions.type are: "Available", "Progressing", and "Degraded" items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map observedGeneration: description: The generation observed by the ControllerRing controller. format: int64 type: integer shards: description: Shards is the total number of shards of this ring. format: int32 type: integer required: - availableShards - shards type: object type: object x-kubernetes-validations: - message: ControllerRing name must not be longer than 63 characters rule: size(self.metadata.name) <= 63 served: true storage: true subresources: status: {} ================================================ FILE: config/default/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../crds - ../sharder components: - ../certificate ================================================ FILE: config/monitoring/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: sharding-system resources: - servicemonitor.yaml # provide prometheus running in namespace "monitoring" with the permissions required for service discovery in namespace # "sharding-system" - prometheus_rbac.yaml ================================================ FILE: config/monitoring/prometheus_rbac.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus name: prometheus-k8s-service-discovery rules: - apiGroups: - "" resources: - services - endpoints - pods verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus name: prometheus-k8s-service-discovery roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: prometheus-k8s-service-discovery subjects: - kind: ServiceAccount name: prometheus-k8s namespace: monitoring ================================================ FILE: config/monitoring/servicemonitor.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: sharder labels: app.kubernetes.io/name: controller-sharding app.kubernetes.io/component: sharder spec: jobLabel: app.kubernetes.io/component endpoints: - path: /metrics port: metrics scheme: https bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token honorLabels: true interval: 10s scrapeTimeout: 10s tlsConfig: insecureSkipVerify: true relabelings: - action: labelmap regex: "__meta_kubernetes_pod_label_label_prometheus_io_(.*)" replacement: "${1}" selector: matchLabels: app.kubernetes.io/name: controller-sharding app.kubernetes.io/component: sharder ================================================ FILE: config/rbac/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - serviceaccount.yaml - leader_election.yaml - metrics_auth.yaml - role.yaml - rolebinding.yaml - pprof_reader.yaml patches: # This is a workaround for controller-gen not being able to handle colons in the role name option. - target: kind: ClusterRole name: sharder patch: | - op: replace path: /metadata/name value: sharding:sharder ================================================ FILE: config/rbac/leader_election.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: sharding:sharder:leader-election rules: - apiGroups: - coordination.k8s.io resources: - leases verbs: - get - create - update - apiGroups: - "" resources: - events verbs: - create - patch --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: sharding:sharder:leader-election roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: sharding:sharder:leader-election subjects: - kind: ServiceAccount name: sharder namespace: sharding-system ================================================ FILE: config/rbac/metrics_auth.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: sharding:metrics-auth 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: sharding:metrics-auth roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: sharding:metrics-auth subjects: - kind: ServiceAccount name: sharder namespace: sharding-system ================================================ FILE: config/rbac/pprof_reader.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: sharding:sharder:pprof-reader rules: - nonResourceURLs: - "/debug/pprof/allocs" - "/debug/pprof/block" - "/debug/pprof/goroutine" - "/debug/pprof/heap" - "/debug/pprof/mutex" - "/debug/pprof/profile" - "/debug/pprof/symbol" - "/debug/pprof/threadcreate" - "/debug/pprof/trace" verbs: - get ================================================ FILE: config/rbac/role.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: sharder rules: - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - "" resources: - namespaces verbs: - get - list - watch - apiGroups: - admissionregistration.k8s.io resources: - mutatingwebhookconfigurations verbs: - create - patch - apiGroups: - coordination.k8s.io resources: - leases verbs: - delete - get - list - patch - update - watch - apiGroups: - sharding.timebertt.dev resources: - controllerrings verbs: - get - list - watch - apiGroups: - sharding.timebertt.dev resources: - controllerrings/status verbs: - patch - update ================================================ FILE: config/rbac/rolebinding.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: sharding:sharder roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: sharding:sharder subjects: - kind: ServiceAccount name: sharder namespace: sharding-system ================================================ FILE: config/rbac/serviceaccount.yaml ================================================ apiVersion: v1 kind: ServiceAccount metadata: name: sharder automountServiceAccountToken: false ================================================ FILE: config/sharder/config.yaml ================================================ apiVersion: config.sharding.timebertt.dev/v1alpha1 kind: SharderConfig webhook: config: annotations: # Technically, this belongs to the certificate component. It doesn't hurt to add this by default though. # Kustomize doesn't allow merging config files in ConfigMaps. Hence, keep the full default config here. cert-manager.io/inject-ca-from: sharding-system/webhook-server ================================================ FILE: config/sharder/deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: sharder namespace: sharding-system labels: app.kubernetes.io/component: sharder spec: replicas: 2 selector: matchLabels: app.kubernetes.io/component: sharder template: metadata: labels: app.kubernetes.io/component: sharder spec: automountServiceAccountToken: true securityContext: runAsNonRoot: true containers: - name: sharder image: sharder:latest args: - --config=/config.yaml volumeMounts: - name: config mountPath: /config.yaml subPath: config env: - name: DISABLE_HTTP2 value: "true" ports: - name: webhook containerPort: 9443 protocol: TCP - name: metrics containerPort: 8080 protocol: TCP securityContext: allowPrivilegeEscalation: false livenessProbe: httpGet: path: /healthz port: 8081 initialDelaySeconds: 15 periodSeconds: 20 readinessProbe: httpGet: path: /readyz port: 8081 initialDelaySeconds: 5 periodSeconds: 10 resources: limits: cpu: 200m memory: 512Mi requests: cpu: 100m memory: 256Mi volumes: - name: config configMap: name: sharder-config serviceAccountName: sharder terminationGracePeriodSeconds: 30 topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: app.kubernetes.io/component: sharder - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: app.kubernetes.io/component: sharder ================================================ FILE: config/sharder/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: sharding-system generatorOptions: disableNameSuffixHash: true labels: - includeSelectors: true pairs: app.kubernetes.io/name: controller-sharding images: - name: sharder newName: ghcr.io/timebertt/kubernetes-controller-sharding/sharder newTag: latest resources: - deployment.yaml - poddisruptionbudget.yaml - service.yaml - ../rbac configMapGenerator: - name: sharder-config options: labels: app.kubernetes.io/component: sharder files: - config=../sharder/config.yaml ================================================ FILE: config/sharder/poddisruptionbudget.yaml ================================================ apiVersion: policy/v1 kind: PodDisruptionBudget metadata: labels: app.kubernetes.io/component: sharder name: sharder spec: maxUnavailable: 1 selector: matchLabels: app.kubernetes.io/component: sharder ================================================ FILE: config/sharder/service.yaml ================================================ apiVersion: v1 kind: Service metadata: name: sharder namespace: sharding-system labels: app.kubernetes.io/component: sharder spec: type: ClusterIP selector: app.kubernetes.io/component: sharder ports: - port: 443 name: webhook protocol: TCP targetPort: webhook - port: 8080 name: metrics protocol: TCP targetPort: metrics ================================================ FILE: docs/README.md ================================================ # Documentation Index - [Getting Started With Controller Sharding](getting-started.md) ⬅️ start here, if you're new to the project - [Install the Sharding Components](installation.md) - [Implement Sharding in Your Controller](implement-sharding.md) - [Monitoring the Sharding Components](monitoring.md) - [Design](design.md) - [Evaluating the Sharding Mechanism](evaluation.md) - [Development and Testing Setup](development.md) ================================================ FILE: docs/design.md ================================================ # Design This document explains the sharding design in more detail. Please also consider reading the respective design chapters in the [study project](https://github.com/timebertt/thesis-controller-sharding) and [Master's thesis](https://github.com/timebertt/masters-thesis-controller-sharding) as long as this document is not detailed enough. ## Architecture This section outlines the key components and mechanism involved in achieving controller sharding. ![Sharding Architecture](assets/architecture.svg) ### The Sharder Component The sharder is a central component deployed once per cluster. It serves as the overall orchestrator of the sharding mechanism. It facilitates membership and failure detection, partitioning, object assignment, and preventing concurrency. The component is designed to be generic, i.e., it can be used for implementing sharding for any kind of controller (independent of the used programming language and controller framework). ### Shard Leases Multiple instances of the actual controller are deployed. Notably, no leader election is performed, and there is no designated single active instance. Instead, each controller instance maintains an individual shard `Lease` labeled with the ring's name, allowing them to announce themselves to the sharder for membership and failure detection. The sharder watches these leases to build a hash ring with the available instances. ### The `ControllerRing` Resource and Sharder Webhook Rings of controllers are configured through the use of the `ControllerRing` custom resource. The sharder creates a `MutatingWebhookConfiguration` for each `ControllerRing` to perform assignments for objects associated with the ring. The sharder webhook is called on `CREATE` and `UPDATE` requests for configured resources, but only for objects that don't have the ring-specific shard label, i.e., for unassigned objects. The sharder uses the consistent hashing ring to determine the desired shard and adds the shard label during admission accordingly. Shards then use a label selector for the shard label with their own instance name to restrict the cache and controller to the subset of objects assigned to them. For the controller's "main" object (configured in `ControllerRing.spec.resources[]`), the object's API group, `kind`, `namespace`, and `name` are concatenated to form its hash key. For objects controlled by other objects (configured in `ControllerRing.spec.resources[].controlledResources[]`), the sharder utilizes information about the controlling object (`ownerReference` with `controller=true`) to calculate the object's hash key. This ensures that owned objects are consistently assigned to the same shard as their owner. ### Object Movements and Rebalancing The sharder also runs a controller that facilitates object movements when necessary. For this, it watches the shard leases and ensures all object assignments are up-to-date whenever the set of available instances changes. It also performs periodic syncs to cater for objects that failed to be assigned during admission. When a shard voluntarily releases its lease (i.e., on graceful shutdown), the sharder recognizes that the shard was removed from the ring and sets its state to `dead`. With this, the shard is no longer considered for object assignments. The orphaned `Lease` is cleaned up after 1 minute. The sharder immediately moves objects that were assigned to the removed shard to the remaining available shards. For this, the controller simply removes the shard label on all affected objects and lets the webhook reassign them. As the original shard is not available anymore, moving the objects doesn't need to be coordinated and the sharder can immediately move objects. When a shard fails to renew its lease in time, the sharder acquires the lease for ensuring API server reachability/functionality. If this is successful, the shard is considered `dead` which leads to forcefully reassigning the objects. When a new shard is added to the ring, the sharder recognizes the available shard lease and performs rebalancing accordingly. In contrast to moving objects from unavailable shards, this needs to be coordinated to prevent multiple shards from acting on the same object concurrently. Otherwise, the shards might perform conflicting actions which might lead to a broken state of the objects. During rebalancing, the sharder drains objects from the old shard by adding the drain label. This operation is acknowledged by the old shard by removing both the shard and the drain label This in turn triggers the sharder webhook again, which assigns the object to the new shard. ## Important Design Decisions ### Don't Watch Sharded Objects Distributing a controller's reconciliations and cache across multiple instances works very well using the label selector approach. I.e., if you run 3 shards you can expect each shard to consume about a third of the CPU and memory consumption that a single instance responsible for all objects would. The key to making Kubernetes controllers horizontally scalable however, is to ensure that the overhead of the sharding mechanism doesn't grow with the number of objects or rate of reconciliations. Otherwise, we would only shift the scalability limitation to another component without removing it. In other words, sharding Kubernetes controller obviously comes with an overhead – just as sharding a database. However, this overhead needs to be constant or at maximum grow in a sublinear fashion. In this project's [first iteration](https://github.com/timebertt/thesis-controller-sharding), the sharder didn't use a webhook to assign objects during admission. Instead, the sharder ran a controller with watches for the sharded objects. Although the sharder used lightweight metadata-only watches, the overhead still grew with the number of sharded objects. In the study project's evaluation (see chapter 6 of the paper), it was shown that the setup was already capable of distributing resource consumption across multiple instances but still faced a scalability limitation in the sharder's resource consumption. In the [second iteration](https://github.com/timebertt/masters-thesis-controller-sharding), the sharder doesn't watch the sharded objects anymore. The watch events were only needed for labeling unassigned objects immediately. This is facilitated by the sharder webhook instead now. The other cases were object assignments need to be performed (membership changes) are unrelated to the objects themselves. Hence, the controller only needs to watch a small number of objects related to the number of shards. With this, the overhead of the sharding mechanism is independent of the number of objects. In fact, it is negligible as show in [Evaluating the Sharding Mechanism](evaluation.md). The comparisons show that the sharder's resource consumption is almost constant apart from spikes during periodic syncs. ### Minimize Impact on the Critical Path While the use of mutating webhooks might allow dropping watches for the sharded objects, they can have a significant impact on API requests, e.g., regarding request latency. To minimize the impact of the sharder's webhook on the overall request latency, the webhook is configured to only react on precisely the set of objects configured in the `ControllerRing` and only for `CREATE` and `UPDATE` requests of unassigned objects. With this the webhook is only on the critical path during initial object creation and whenever the set of available shards requires reassignments. Furthermore, webhooks can cause API requests to fail entirely. To reduce the risk of such failures, the sharder is deployed in a highly available fashion and the webhook is configured with a low timeout and failure policy `Ignore`. With this, API requests still succeed if the webhook server is shortly unreachable. In such cases, the object will be unassigned until the next sync of the sharder controller. I.e., the design prioritizes availability of the API over consistency of assignments. Also, the sharding mechanism doesn't touch the critical path of actual reconciliations. ### Minimize Impact on the Control Plane By using label selectors on the watch connections of individual shards, the load on the API server is not changed compared to a single controller instance that watches all objects without a selector. Additionally, the sharder minimizes the extra load on the API server and etcd when it comes to `LIST` requests of all sharded objects (e.g., during periodic syncs). For this, it only lists the metadata of the sharded objects (spec and status are irrelevant). Also, it passes the [request parameter](https://kubernetes.io/docs/reference/using-api/api-concepts/#the-resourceversion-parameter) `resourceVersion=0` to the API server, which causes it to serve the request from the in-memory watch cache instead of performing a quorum read on etcd. In other words, the design accepts slightly outdated data and with this slightly inconsistent object assignments in favor of better performance and scalability. ## Limitations ### Limited Support for `generateName` In the first iteration (without the sharder webhook), the object's `uid` was the essential part of the hash key. With the evolution of the mechanism to assign objects during admission using a mutating webhook, the object's `uid` cannot be used any longer as it is unset during admission for `CREATE` requests. Hence, the sharder uses the object's `GroupVersionKind`, `namespace`, and `name` for calculating the hash key instead. This works well and also supports calculating the same hash key for controlled objects by using information from `ownerReferences`. However, this also means that `generateName` is not supported for resources that are not controlled by other resources in the ring. The reason is that `generateName` is not set during admission for `CREATE` requests similar to the `uid` field. Note, that `generateName` is still supported for objects that are controlled by other objects, as the controlled object's own name is not included in the hash key. This tradeoff seems acceptable, as there are not many good use cases for `generateName`. In general, using `generateName` in controllers makes it difficult to prevent incorrect actions (e.g., creating too many controlled objects) as the controller needs to track its own actions that used `generateName`. Instead, using deterministic naming based on the owning object (e.g., spec contents or `uid`) simplifies achieving correctness significantly. All other use cases of using `generateName` for simply generating a random name of an object one doesn't really care about (e.g., in integration or load tests) can also generate a random suffix on the client side before submitting the request to the API server. However, if the API server set an object's `uid` or `generateName` before admission for `CREATE` requests, this limitation could be lifted. ================================================ FILE: docs/development.md ================================================ # Development and Testing Setup This document explains more details of the development and testing setup that is also presented in [Getting Started With Controller Sharding](getting-started.md). ## Development Cluster The setup's basis is a local [kind](https://kind.sigs.k8s.io/) cluster. This simplifies developing and testing the project as it comes without additional cost, can be thrown away easily, and one doesn't need to push development images to a remote registry. In other words, there are no prerequisites for getting started with this project other than a [Go](https://go.dev/) and [Docker](https://www.docker.com/) installation. ```bash # create a local cluster make kind-up # target the kind cluster export KUBECONFIG=$PWD/hack/kind_kubeconfig.yaml # delete the local cluster make kind-down ``` If you want to use another cluster for development (e.g., a remote cluster) simply set the `KUBECONFIG` environment variable as usual and all make commands will target the cluster pointed to by your kubeconfig. Note that you might need to push images to a remote registry though. ## Components The development setup reuses the deployment manifests of the main sharding components developed in this repository, located in [`config`](../config). See [Install the Sharding Components](installation.md). It also includes the [checksum-controller](../cmd/checksum-controller) as an example sharded controller (see [Implement Sharding in Your Controller](implement-sharding.md)) and the [webhosting-operator](../webhosting-operator/README.md) (see [Evaluating the Sharding Mechanism](evaluation.md)). Apart from this, the development setup also includes some external components, located in [`hack/config`](../hack/config). This includes [cert-manager](https://cert-manager.io/), [ingress-nginx](https://kubernetes.github.io/ingress-nginx/), [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus), [kyverno](https://kyverno.io/), and [parca](https://parca.dev/). These components are installed for a seamless development and testing experience but also for this project's [Evaluation](evaluation.md) on a remote cluster in the cloud. ## Deploying, Building, Running Using Skaffold Use `make deploy` to deploy all components with pre-built images using [skaffold](https://skaffold.dev/). You can overwrite the used images via make variables, e.g., the `TAG` variable: ```bash make deploy TAG=latest ``` For development, skaffold can build fresh images based on your local changes using [ko](https://ko.build/), load them into your local cluster, and deploy the configuration: ```bash make up ``` Alternatively, you can also start a skaffold-based dev loop which can automatically rebuild and redeploy images as soon as source files change: ```bash make dev # runs initial build and deploy... # press any key to trigger a fresh build after changing sources ``` If you're not working with a local kind cluster, you need to set `SKAFFOLD_DEFAULT_REPO` to a registry that you can push the dev images to: ```bash make up SKAFFOLD_DEFAULT_REPO=ghcr.io/timebertt/dev-images ``` Remove all components from the cluster: ```bash make down ``` For any skaffold-based make command, you can set `SKAFFOLD_MODULE` to target only a specific part of the [skaffold configuration](../hack/config/skaffold.yaml): ```bash make dev SKAFFOLD_MODULE=sharder ``` ## Running on the Host Machine Instead of running the sharder in the cluster, you can also run it on your host machine targeting your local kind cluster. This doesn't deploy all components as before but only cert-manager for injecting the webhook's CA bundle. Assuming a fresh kind cluster: ```bash make run ``` Now, create the `ControllerRing` and run a local `checksum-controller`: ```bash make run-checksum-controller ``` You should see that the shard successfully announced itself to the sharder: ```bash $ kubectl get lease -L alpha.sharding.timebertt.dev/controllerring,alpha.sharding.timebertt.dev/state NAME HOLDER AGE CONTROLLERRING STATE checksum-controller-lhrlt6h4 checksum-controller-lhrlt6h4 6s checksum-controller ready $ kubectl get controllerring NAME READY AVAILABLE SHARDS AGE checksum-controller True 1 1 13s ``` Running the `checksum-controller` locally gives you the option to test non-graceful termination, i.e., a scenario where the shard fails to renew its lease in time. Simply press `Ctrl-C` twice: ```bash make run-checksum-controller ... ^C2023-11-24T15:16:50.948+0100 INFO Shutting down gracefully in 2 seconds, send another SIGINT or SIGTERM to shutdown non-gracefully ^Cexit status 1 ``` ## Testing the Sharding Setup Independent of the used setup (skaffold-based or running on the host machine), you should be able to create sharded `Secrets` in the `default` namespace as configured in the `example` `ControllerRing`. The `ConfigMaps` created by the `checksum-controller` should be assigned to the same shard as the owning `Secret`: ```bash $ kubectl create secret generic foo --from-literal foo=bar secret/foo created $ kubectl get cm,secret -L shard.alpha.sharding.timebertt.dev/checksum-controller NAME DATA AGE CHECKSUM-CONTROLLER configmap/checksums-foo 1 1s checksum-controller-lhrlt6h4 NAME TYPE DATA AGE CHECKSUM-CONTROLLER secret/foo Opaque 1 1s checksum-controller-lhrlt6h4 ``` ## Monitoring When using the skaffold-based setup, you also get a full monitoring setup for observing and analyzing the components' resource usage. To access the monitoring dashboards and metrics in Grafana, simply forward its port and open http://localhost:3000/ in your browser: ```bash kubectl -n monitoring port-forward svc/grafana 3000 & ``` The password for Grafana's `admin` user is written to `hack/config/monitoring/default/grafana_admin_password.secret.txt`. Be sure to check out the controller-runtime dashboard: http://localhost:3000/d/PuCBL3zVz/controller-runtime-controllers ## Continuous Profiling To dig deeper into the components' resource usage, you can deploy the continuous profiling setup based on [Parca](https://parca.dev/): ```bash make up SKAFFOLD_MODULE=profiling SKAFFOLD_PROFILE=profiling ``` To access the profiling data in Parca, simply forward its port and open http://localhost:7070/ in your browser: ```bash kubectl -n parca port-forward svc/parca 7070 & ``` For accessing Parca through its `Ingress`, use the basic auth password for the `parca` user from `hack/config/profiling/parca_password.secret.txt`. Note that the Parca deployment doesn't implement retention for profiling data. I.e., the Parca data volume will grow infinitely as long as Parca is running. To shut down Parca after analyzing the collected profiles and destroying the persistent volume use the following command: ```bash make down SKAFFOLD_MODULE=profiling SKAFFOLD_PROFILE=profiling ``` ================================================ FILE: docs/evaluation.md ================================================ # Evaluating the Sharding Mechanism This guide describes how the sharding mechanism implemented in this repository is evaluated and outlines the key results of the evaluation performed in the associated [Master's thesis](https://github.com/timebertt/masters-thesis-controller-sharding). Please refer to the thesis' evaluation section for more details. ## Components The evaluation setup builds upon the [Development and Testing Setup](development.md) but adds a few more components. To demonstrate and evaluate the implemented sharding mechanisms using a fully functioning controller, a dedicated example operator was developed: the [webhosting-operator](../webhosting-operator/README.md). While the webhosting-operator is developed in the same repository, it only serves as an example. When deploying the sharding components using `make deploy` or `make up`, the webhosting-operator is automatically deployed along with the other evaluation components. Assuming you're in the repository's root directory, you can deploy the webhosting-operator using: ```bash # deploy the webhosting-operator using pre-built images make deploy SKAFFOLD_MODULE=webhosting-operator TAG=latest # alternatively, build and deploy fresh images make up SKAFFOLD_MODULE=webhosting-operator ``` To perform a quick test of the webhosting-operator, create some example `Website` objects: ```bash $ kubectl apply -k webhosting-operator/config/samples ... $ kubectl -n project-foo get website,deploy,ing,svc,cm -L shard.alpha.sharding.timebertt.dev/webhosting-operator NAME THEME PHASE SINCE AGE WEBHOSTING-OPERATOR website.webhosting.timebertt.dev/kubecon exciting Ready 1s 3s webhosting-operator-5f7854768d-8n59m website.webhosting.timebertt.dev/library lame Ready 1s 3s webhosting-operator-5f7854768d-j67tj NAME READY UP-TO-DATE AVAILABLE AGE WEBHOSTING-OPERATOR deployment.apps/kubecon-b5ed55 1/1 1 1 3s webhosting-operator-5f7854768d-8n59m deployment.apps/library-185298 1/1 1 1 3s webhosting-operator-5f7854768d-j67tj NAME CLASS HOSTS ADDRESS PORTS AGE WEBHOSTING-OPERATOR ingress.networking.k8s.io/kubecon-b5ed55 nginx webhosting.timebertt.dev 80, 443 3s webhosting-operator-5f7854768d-8n59m ingress.networking.k8s.io/library-185298 nginx webhosting.timebertt.dev 80, 443 3s webhosting-operator-5f7854768d-j67tj NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE WEBHOSTING-OPERATOR service/kubecon-b5ed55 ClusterIP 100.82.167.176 8080/TCP 3s webhosting-operator-5f7854768d-8n59m service/library-185298 ClusterIP 100.82.224.52 8080/TCP 3s webhosting-operator-5f7854768d-j67tj NAME DATA AGE WEBHOSTING-OPERATOR configmap/kubecon-b5ed55 2 3s webhosting-operator-5f7854768d-8n59m configmap/library-185298 2 3s webhosting-operator-5f7854768d-j67tj ``` You can now visit the created websites at http://localhost:8088/project-foo/homepage and http://localhost:8088/project-foo/official. You can also visit your [local webhosting dashboard](http://127.0.0.1:3000/d/NbmNpqEnk/webhosting?orgId=1) after forwarding the Grafana port: ```bash kubectl -n monitoring port-forward svc/grafana 3000 ``` This dashboard uses metrics exported by [webhosting-operator](../webhosting-operator/pkg/metrics) about its API objects, i.e., `kube_website_*` and `kube_theme_*`. There is also a dashboard about the [sharding of websites](http://127.0.0.1:3000/d/7liIybkVk/sharding?orgId=1). In addition to creating the preconfigured websites, you can also generate some more random websites using the [samples-generator](../webhosting-operator/cmd/samples-generator): ```bash # create a random number of websites per project namespace (up to 50 each) $ go run ./webhosting-operator/cmd/samples-generator created 32 Websites in project "project-foo" ``` ## Load Tests The [experiment](./cmd/experiment) tool allows executing different scenarios for load testing the webhosting-operator, which are used for evaluating the sharding mechanism: ```text $ go run ./webhosting-operator/cmd/experiment -h Usage: experiment [command] Available Scenarios basic Basic load test, create 9k websites in 15 minutes chaos Create 4.5k websites over 15 minutes and terminate a random shard every 5 minutes rolling-update Create 9k websites in 15 minutes while rolling the operator scale-out Measure scale-out properties with a high churn rate ... ``` A load test scenario can be executed using one of these commands: ```bash # run the basic scenario from your development machine (not recommended) go run ./cmd/experiment basic # build the experiment image and run the basic scenario as a Job on the cluster make up SKAFFOLD_MODULE=experiment EXPERIMENT_SCENARIO=basic # use a pre-built experiment image to run the basic scenario as a Job on the cluster make deploy SKAFFOLD_MODULE=experiment EXPERIMENT_SCENARIO=basic TAG=latest ``` All scenarios put load on webhosting-operator by creating and mutating a large amount of `Website` objects. However, creating soo many `Websites` would waste immense compute power just to run thousands of dummy websites. Hence, webhosting-operator creates `Deployments` of `Websites` in load tests with `spec.replicas=0`. It also doesn't expose `Websites` created in load tests via `Ingress` objects by setting `spec.ingressClassName=fake`. Otherwise, this would overload the ingress controller, which is not what the experiment is actually supposed to load test. When running load test experiments on the cluster, a `ServiceMonitor` is created to instruct prometheus to scrape `experiment`. As the tool is based on controller-runtime as well, the controller-runtime metrics can be used for visualizing the load test scenario and verifying that the tool is able to generate the desired load. ## Experiment Setup As a local kind cluster cannot handle such high load, a remote cluster is used to perform the load test experiments. For this, a [Gardener](https://github.com/gardener/gardener) installation on [STACKIT](https://www.stackit.de/en/) is used to create a cluster based on the [sample manifest](../hack/config/shoot.yaml). [external-dns](https://github.com/kubernetes-sigs/external-dns) is used for publicly exposing the monitoring and continuous profiling endpoints, as well as `Websites` created outside of load test experiments. ```bash # gardenctl target --garden ... kubectl apply -f hack/config/shoot.yaml # gardenctl target --shoot ... kubectl apply --server-side -k hack/config/external-dns kubectl -n external-dns create secret generic google-clouddns-timebertt-dev --from-literal project=$PROJECT_NAME --from-file service-account.json=$SERVICE_ACCOUNT_FILE # gardenctl target --control-plane kubectl apply --server-side -k hack/config/policy/controlplane ``` In addition to the described components, [kyverno](https://github.com/kyverno/kyverno) is deployed to the cluster itself (shoot cluster) and to the control plane (seed cluster). In the cluster itself, kyverno policies are used for scheduling the sharder and webhosting-operator to the dedicated `sharding` worker pool and experiment to the dedicated `experiment` worker pool. This makes sure that these components run on machines isolated from other system components and don't content for compute resources during load tests. Furthermore, kyverno policies are added to the control plane to ensure a static size of etcd, kube-apiserver, and kube-controller-manager (requests=limits for guaranteed resources, disable vertical autoscaling, 4 replicas of kube-apiserver and disable horizontal autoscaling). Also, kube-controller-manager's client-side rate limiting is disabled (ref https://github.com/timebertt/kubernetes-controller-sharding/pull/610, [SIG api-machinery recommendation](https://kubernetes.slack.com/archives/C0EG7JC6T/p1680889646346859?thread_ts=1680791299.631439&cid=C0EG7JC6T)) and HTTP/2 is disabled so that API requests are distributed across API server instances (ref https://github.com/gardener/gardener/issues/8810). This is done to make load test experiments more stable and their results more reproducible. ## Measurements After executing a load test experiment, the [measure](../webhosting-operator/cmd/measure) tool is used for retrieving the key metrics from Prometheus. It takes a configurable set of measurements in the form of Prometheus queries and stores them in CSV-formatted files for further analysis (with numpy/pandas) and visualization (with matplotlib). Please see the [results directory](https://github.com/timebertt/masters-thesis-controller-sharding/tree/main/results) in the Master's thesis' repository for the exact measurements taken. The scale of the controller setup is measured in two dimensions: 1. The number of API objects that the controller watches and reconciles. 2. The churn rate of API objects, i.e., the rate of object creations, updates, and deletions. ```yaml queries: - name: website-count # dimension 1 query: | sum(kube_website_info) - name: website-churn # dimension 2 query: | sum(rate( controller_runtime_reconcile_total{ job="experiment", result!="error", controller=~"website-(generator|deleter|mutator)" }[1m] )) by (controller) ``` ## SLIs / SLOs To consider a controller setup as performing adequately, the following SLOs need to be satisfied: 1. The time of enqueuing object keys for reconciliation for every controller, measured as the 99th percentile per cluster-day, is at maximum 1 second. 2. The latency of realizing the desired state of objects for every controller, excluding reconciliation time of controlled objects, until observed by a watch request, measured as the 99th percentile per cluster-day, is at maximum x, where x depends on the controller. In case of the `Website` controller, 5 is chosen for x. ```yaml queries: - name: latency-queue # SLO 1 type: instant slo: 1 query: | histogram_quantile(0.99, sum by (le) (rate( workqueue_queue_duration_seconds_bucket{ job="webhosting-operator", name="website" }[$__range] ))) - name: latency-reconciliation # SLO 2 type: instant slo: 5 query: | histogram_quantile(0.99, sum by (le) (rate( experiment_website_reconciliation_duration_seconds_bucket{ job="experiment" }[$__range] ))) ``` ## Comparison The following graphs show the generated load and compare the resulting CPU, memory, and network usage of the components in three different setups when running the `basic` experiment scenario (~9k websites created over 15m): - external sharder: 3 webhosting-operator pods (shards) + 2 sharder pods (the new approach implemented in this repository, second iteration for the Master's thesis) - internal sharder: 3 webhosting-operator pods (3 shards, 1 acts as the sharder) (the old approach, first iteration for the study project) - singleton: 1 webhosting-operator pod (traditional leader election setup without sharding) ![Generated load in basic scenario](assets/comparison-load.svg) ![CPU comparison in basic scenario](assets/comparison-cpu.svg) ![Memory comparison in basic scenario](assets/comparison-memory.svg) ![Network comparison in basic scenario](assets/comparison-network.svg) The new external sharding approach proves to scale best. The individual shards consume about a third of the singleton controller's usage (close to optimum). Also, the sharder pods consume a low static amount of resources. Most importantly, the sharder's resource usage is independent of the number of sharded objects. ## Horizontal Scalability To evaluate the horizontal scalability of the sharding mechanism (external sharder), the maximum load capacity is determined for different numbers of instances (1, 2, 3, 4, 5). While the load increases, cumulative SLIs from the start of the experiment are calculated. When the cumulative SLI grows above the SLO, the current count and churn rate are the maximum load capacity. As shown in the last plot, the system's capacity increases almost linearly with the number of added instances. ![Generated load in scale-out scenario](assets/scale-out-load.svg) ![Cumulative controller SLIs in scale-out scenario](assets/scale-out-slis.svg) ![Load capacity increase with added instances in scale-out scenario](assets/scale-out-capacity.svg) ================================================ FILE: docs/getting-started.md ================================================ # Getting Started With Controller Sharding This guide walks you through getting started with controller sharding in a local cluster. It sets up the sharder and an example sharded controller so that you can see the components in action. This is great for trying out the project for the first time and learning about the basic concepts. ## Setup Create a local cluster using [kind](https://kind.sigs.k8s.io/) and deploy all components: ```bash make kind-up export KUBECONFIG=$PWD/hack/kind_kubeconfig.yaml make deploy TAG=latest ``` The sharder is running in the `sharding-system` namespace and the example shard (checksum-controller) is deployed to the `default` namespace: ```bash $ kubectl -n sharding-system get po NAME READY STATUS RESTARTS AGE sharder-99fcf97b4-hpm6w 1/1 Running 0 17s sharder-99fcf97b4-zr7rj 1/1 Running 0 17s $ kubectl get po NAME READY STATUS RESTARTS AGE checksum-controller-c95c4fdb6-7jb2v 1/1 Running 0 18s checksum-controller-c95c4fdb6-hv8pb 1/1 Running 0 18s checksum-controller-c95c4fdb6-rtvrm 1/1 Running 0 18s ``` ## The `ControllerRing` and `Lease` Objects We can see that the `ControllerRing` object is ready and reports 3 available shards out of 3 total shards: ```bash $ kubectl get controllerring checksum-controller NAME READY AVAILABLE SHARDS AGE checksum-controller True 3 3 25s ``` All shards announce themselves to the sharder by maintaining an individual `Lease` object with the `alpha.sharding.timebertt.dev/controllerring` label. We can observe that the sharder recognizes all shards as available by looking at the `alpha.sharding.timebertt.dev/state` label: ```bash $ kubectl get lease -L alpha.sharding.timebertt.dev/controllerring,alpha.sharding.timebertt.dev/state NAME HOLDER AGE CONTROLLERRING STATE checksum-controller-c95c4fdb6-7jb2v checksum-controller-c95c4fdb6-7jb2v 44s checksum-controller ready checksum-controller-c95c4fdb6-hv8pb checksum-controller-c95c4fdb6-hv8pb 44s checksum-controller ready checksum-controller-c95c4fdb6-rtvrm checksum-controller-c95c4fdb6-rtvrm 44s checksum-controller ready ``` The `ControllerRing` object specifies which API resources should be sharded. Optionally, it allows selecting the namespaces in which API resources are sharded: ```yaml apiVersion: sharding.timebertt.dev/v1alpha1 kind: ControllerRing metadata: name: checksum-controller spec: resources: - group: "" resource: secrets controlledResources: - group: "" resource: configmaps namespaceSelector: matchLabels: kubernetes.io/metadata.name: default ``` In our case, the `checksum-controller` reconciles `Secrets` in the `default` namespace and creates a `ConfigMap` including the secret data's checksums. The created `ConfigMaps` are controlled by the respective `Secret`, i.e., there they have an `ownerReference` with `controller=true` to the `Secret`. ## The Sharder Webhook The sharder created a `MutatingWebhookConfiguration` for the resources listed in our `ControllerRing` specification: ```bash $ kubectl get mutatingwebhookconfiguration -l alpha.sharding.timebertt.dev/controllerring=checksum-controller NAME WEBHOOKS AGE controllerring-checksum-controller 1 71s ``` Let's examine the webhook configuration for more details. We can see that the webhook targets a ring-specific path served by the `sharder`. It reacts on `CREATE` and `UPDATE` requests of the configured resources, where the object doesn't have the ring-specific shard label. I.e., it gets called for unassigned objects and adds the shard assignment label during admission. ```yaml apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: name: controllerring-checksum-controller webhooks: - clientConfig: service: name: sharder namespace: sharding-system path: /webhooks/sharder/controllerring/checksum-controller port: 443 name: sharder.sharding.timebertt.dev namespaceSelector: matchLabels: kubernetes.io/metadata.name: default objectSelector: matchExpressions: - key: shard.alpha.sharding.timebertt.dev/checksum-controller operator: DoesNotExist rules: - apiGroups: - "" apiVersions: - '*' operations: - CREATE - UPDATE resources: - secrets scope: '*' - apiGroups: - "" apiVersions: - '*' operations: - CREATE - UPDATE resources: - configmaps scope: '*' ``` ## Creating Sharded Objects We can observe the behavior of the webhook by creating a first example object. When we create a `Secret`, the webhook assigns it to one of the available controller instances by adding the ring-specific shard label. It performs a consistent hashing algorithm, where it hashes both the object's key (consisting of API group, `kind`, `namespace`, and `name`) and the shards' names onto a virtual ring. It picks the shard with the hash value that is next to the object's hash clock-wise. ```bash $ kubectl create secret generic foo --from-literal foo=bar -oyaml apiVersion: v1 data: foo: YmFy kind: Secret metadata: labels: shard.alpha.sharding.timebertt.dev/checksum-controller: checksum-controller-c95c4fdb6-hv8pb name: foo namespace: default type: Opaque ``` We can see that the responsible shard reconciled the `Secret` and created a `ConfigMap` for it. Similar to the `Secret`, the `ConfigMap` was also assigned by the webhook. In this case however, the sharder uses the information about the owning `Secret` for calculating the object's hash key. With this, owned objects are always assigned to the same shard as their owner. This is done because the controller typically needs to reconcile the owning object whenever the status of an owned object changes. E.g., the `Deployment` controller watches `ReplicaSets` and continues rolling updates of the owning `Deployment` as soon as the owned `ReplicaSet` has the number of wanted replicas. ```bash $ kubectl get configmap checksums-foo -oyaml apiVersion: v1 data: foo: fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 kind: ConfigMap metadata: labels: shard.alpha.sharding.timebertt.dev/checksum-controller: checksum-controller-c95c4fdb6-hv8pb name: checksums-foo namespace: default ownerReferences: - apiVersion: v1 controller: true kind: Secret name: foo ``` Let's create a few more `Secrets` and observe the distribution of objects across shards: ```bash $ for i in $(seq 1 9); do k create secret generic foo$i ; done $ kubectl get secret,configmap -L shard.alpha.sharding.timebertt.dev/checksum-controller NAME TYPE DATA AGE CHECKSUM-CONTROLLER secret/foo Opaque 1 39s checksum-controller-c95c4fdb6-hv8pb secret/foo1 Opaque 0 10s checksum-controller-c95c4fdb6-rtvrm secret/foo2 Opaque 0 10s checksum-controller-c95c4fdb6-7jb2v secret/foo3 Opaque 0 10s checksum-controller-c95c4fdb6-rtvrm secret/foo4 Opaque 0 10s checksum-controller-c95c4fdb6-hv8pb secret/foo5 Opaque 0 10s checksum-controller-c95c4fdb6-rtvrm secret/foo6 Opaque 0 10s checksum-controller-c95c4fdb6-hv8pb secret/foo7 Opaque 0 10s checksum-controller-c95c4fdb6-7jb2v secret/foo8 Opaque 0 10s checksum-controller-c95c4fdb6-rtvrm secret/foo9 Opaque 0 10s checksum-controller-c95c4fdb6-hv8pb NAME DATA AGE CHECKSUM-CONTROLLER configmap/checksums-foo 1 39s checksum-controller-c95c4fdb6-hv8pb configmap/checksums-foo1 0 10s checksum-controller-c95c4fdb6-rtvrm configmap/checksums-foo2 0 10s checksum-controller-c95c4fdb6-7jb2v configmap/checksums-foo3 0 10s checksum-controller-c95c4fdb6-rtvrm configmap/checksums-foo4 0 10s checksum-controller-c95c4fdb6-hv8pb configmap/checksums-foo5 0 10s checksum-controller-c95c4fdb6-rtvrm configmap/checksums-foo6 0 10s checksum-controller-c95c4fdb6-hv8pb configmap/checksums-foo7 0 10s checksum-controller-c95c4fdb6-7jb2v configmap/checksums-foo8 0 10s checksum-controller-c95c4fdb6-rtvrm configmap/checksums-foo9 0 10s checksum-controller-c95c4fdb6-hv8pb ``` ## Removing Shards From the Ring Let's see what happens when the set of available shards changes. We can observe the actions that the sharder takes using `kubectl get secret --show-labels -w --output-watch-events --watch-only` in a new terminal session. First, let's scale down the sharded controller to remove one shard from the ring: ```bash $ kubectl scale deployment checksum-controller --replicas 2 deployment.apps/checksum-controller scaled ``` The shard releases its `Lease` by setting the `holderIdentity` field to the empty string. The sharder recognizes that the shard was removed from the ring and sets its state to `dead`. With this, the shard is no longer considered for object assignments. The orphaned `Lease` is cleaned up after 1 minute. ```bash $ kubectl get lease -L alpha.sharding.timebertt.dev/state NAME HOLDER AGE STATE checksum-controller-c95c4fdb6-7jb2v checksum-controller-c95c4fdb6-7jb2v 3m34s ready checksum-controller-c95c4fdb6-hv8pb checksum-controller-c95c4fdb6-hv8pb 3m34s ready checksum-controller-c95c4fdb6-rtvrm 3m34s dead ``` We can observe that the sharder immediately moved objects that were assigned to the removed shard to the remaining available shards. For this, the sharder controller simply removes the shard label on all affected objects and lets the webhook reassign them. As the original shard is not available anymore, moving the objects doesn't need to be coordinated and the sharder can immediately move objects. ```bash $ kubectl get secret --show-labels -w --output-watch-events --watch-only EVENT NAME TYPE DATA AGE LABELS MODIFIED foo1 Opaque 0 48s shard.alpha.sharding.timebertt.dev/checksum-controller=checksum-controller-c95c4fdb6-hv8pb MODIFIED foo3 Opaque 0 48s shard.alpha.sharding.timebertt.dev/checksum-controller=checksum-controller-c95c4fdb6-7jb2v MODIFIED foo5 Opaque 0 48s shard.alpha.sharding.timebertt.dev/checksum-controller=checksum-controller-c95c4fdb6-hv8pb MODIFIED foo8 Opaque 0 48s shard.alpha.sharding.timebertt.dev/checksum-controller=checksum-controller-c95c4fdb6-7jb2v ``` ## Adding Shards to the Ring Now, let's scale up our sharded controller to add a new shard to the ring. ```bash $ kubectl scale deployment checksum-controller --replicas 3 deployment.apps/checksum-controller scaled ``` We can observe that the new `Lease` object is in state `ready`. With this, the new shard is immediately considered for assignment of new objects. ```bash $ kubectl get lease -L alpha.sharding.timebertt.dev/state NAME HOLDER AGE STATE checksum-controller-c95c4fdb6-7jb2v checksum-controller-c95c4fdb6-7jb2v 4m19s ready checksum-controller-c95c4fdb6-hv8pb checksum-controller-c95c4fdb6-hv8pb 4m19s ready checksum-controller-c95c4fdb6-kdrss checksum-controller-c95c4fdb6-kdrss 4s ready ``` In this case, a rebalancing needs to happen and the sharder needs to move objects away from available shards to the new shard. In contrast to moving objects from unavailable shards, this needs to be coordinated to prevent multiple shards from acting on the same object concurrently. Otherwise, the shards might perform conflicting actions which might lead to a broken state of the objects. For this, the sharder adds the drain label to all objects that should be moved to the new shard. This asks the currently responsible shard to stop reconciling the object and acknowledge the movement. As soon as the controller observes the drain label, it removes it again along with the shard label. This triggers the sharder webhook which immediately assigns the object to the desired shard. ```bash $ kubectl get secret --show-labels -w --output-watch-events --watch-only EVENT NAME TYPE DATA AGE LABELS MODIFIED foo5 Opaque 0 116s drain.alpha.sharding.timebertt.dev/checksum-controller=true,shard.alpha.sharding.timebertt.dev/checksum-controller=checksum-controller-c95c4fdb6-hv8pb MODIFIED foo8 Opaque 0 116s drain.alpha.sharding.timebertt.dev/checksum-controller=true,shard.alpha.sharding.timebertt.dev/checksum-controller=checksum-controller-c95c4fdb6-7jb2v MODIFIED foo5 Opaque 0 116s shard.alpha.sharding.timebertt.dev/checksum-controller=checksum-controller-c95c4fdb6-kdrss MODIFIED foo8 Opaque 0 116s shard.alpha.sharding.timebertt.dev/checksum-controller=checksum-controller-c95c4fdb6-kdrss ``` ## Clean Up Simply delete the local cluster to clean up: ```bash make kind-down ``` ## Where To Go From Here? Now, you should have a basic understanding of how sharding for Kubernetes controllers works. If you want to learn more about the individual components, the sharding architecture, and the reasoning behind it, see [Design](design.md). You might also be interested in reading the [Evaluation](evaluation.md) document about load tests for sharded controllers and how this project helps in scaling Kubernetes controllers. If you want to use sharding for your own controllers, see [Implement Sharding in Your Controller](implement-sharding.md). To further experiment with the setup from this guide or to start developing changes to the sharding components, see [Development and Testing Setup](development.md). You can also take a look at the remaining docs in the [documentation index](README.md). ================================================ FILE: docs/implement-sharding.md ================================================ # Implement Sharding in Your Controller This guide walks you through implementing sharding for your own controller. Prerequisite for using a sharded controller setup is to install the sharding components in the cluster, see [Install the Sharding Components](installation.md). ## Configuring the `ControllerRing` After installing the sharding components, you can go ahead and configure a `ControllerRing` object for your controller. For all controllers that you want to shard, configure the controller's main resource and the controlled resources in `ControllerRing.spec.resources`. As an example, let's consider a subset of kube-controller-manager's controllers: `Deployment` and `ReplicaSet`. - The `Deployment` controller reconciles the `deployments` resource and controls `replicasets`. - The `ReplicaSet` controller reconciles the `replicaset` resource and controls `pods`. The corresponding `ControllerRing` for the `Deployment` controller would need to be configured like this: ```yaml apiVersion: sharding.timebertt.dev/v1alpha1 kind: ControllerRing metadata: name: kube-controller-manager-deployment spec: resources: - group: apps resource: deployments controlledResources: - group: apps resource: replicasets ``` Note that the `ControllerRing` name must not be longer than 63 characters because it is used as part of the shard and drain label key (see below). To allow the sharder to reassign the sharded objects during rebalancing, we need to grant the corresponding permissions. We need to grant these permissions explicitly depending on what is configured in the `ControllerRing`. Otherwise, the sharder would basically require `cluster-admin` access. For the above example, we would use these RBAC manifests: ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: sharding:controllerring:kube-controller-manager rules: - apiGroups: - apps resources: - deployments - replicaset verbs: - list - patch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: sharding:controllerring:kube-controller-manager roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: sharding:controllerring:kube-controller-manager subjects: - kind: ServiceAccount name: sharder namespace: sharding-system ``` ## Implementation Changes To support sharding in your Kubernetes controller, only three aspects need to be implemented: - announce ring membership and shard health: maintain individual shard `Leases` instead of performing leader election on a single `Lease` - only watch, cache, and reconcile objects assigned to the respective shard: add a shard-specific label selector to watches - acknowledge object movements during rebalancing: remove the drain and shard label when the drain label is set and stop reconciling the object [`pkg/shard`](../pkg/shard) contains reusable reference implementations for these aspects. [`cmd/checksum-controller`](../cmd/checksum-controller) serves as an example implementation for sharded controllers that shows how to put the pieces together in controllers based on [controller-runtime](https://github.com/kubernetes-sigs/controller-runtime). However, sharding can also be implemented in controllers that don't use controller-runtime or that are written in another programming language than Go. The following sections outline the exact requirements that a sharded controller needs to fulfill and then show how to implement them in controllers based on controller-runtime. Don't be scared by the long descriptions. Implementing these aspects is simple (especially if reusing the helpers designed for controller-runtime controllers) and only needs to be done once. The long descriptions just make sure the requirements are perfectly clear if you need to implement them yourself. ### Shard Lease In short: ensure your shard maintains a `Lease` object like this and only runs its controllers as long as it holds the `Lease`: ```yaml apiVersion: coordination.k8s.io/v1 kind: Lease metadata: labels: alpha.sharding.timebertt.dev/controllerring: my-controllerring name: my-operator-565df55f4b-5vwpj namespace: operator-system spec: holderIdentity: my-operator-565df55f4b-5vwpj # needs to equal the Lease's name leaseDurationSeconds: 15 # pick whatever you would use for leader election as well ``` Most controllers already perform leader election using a central `Lease` lock object. Only if the instance is elected as the leader, it is allowed to run the controllers. If it fails to renew the `Lease` in time, another instance is allowed to acquire the `Lease` and can run the controllers. Hence, an instance must not run any controllers when it looses its `Lease`. In fact, most implementations exit the entire process when failing to renew the lock for safety. On graceful termination (e.g., during a rolling update), the active leader may release the lock by setting the `holderIdentity` field of the `Lease` to the empty string. This allows another instance to acquire the `Lease` immediately without waiting for it to expire, which helps in quick leadership handovers. The same mechanisms apply to sharded controllers. But instead of using a central `Lease` object for all instances, each instance acquires and maintains its own `Lease` object to announce itself to the sharder. A shard may only run its controllers as long as it holds its shard `Lease`. I.e., when it fails to renew the shard `Lease` in time, it also needs to stop all controllers. Similar to usual leader election, a shard may release its own shard `Lease` on graceful termination by removing the `holderIdentity`. This immediately triggers reassignments by the sharder to minimize the duration where no shard is acting on a subset of objects. In essence, all the existing machinery for leader election can be reused for maintaining the shard `Lease` – that is, with two minor changes. First, the shard `Lease` needs to be labelled with `alpha.sharding.timebertt.dev/controllerring=` to specify which `ControllerRing` the shard belongs to. Second, the name of the shard `Lease` needs to match the `holderIdentity`. By default, the instance's hostname is used for both values. If the `holderIdentity` differs from the name, the sharder assumes that the shard is unavailable. In controller-runtime, you can configure your shard to maintain its shard `Lease` as follows: ```go package main import ( shardlease "github.com/timebertt/kubernetes-controller-sharding/pkg/shard/lease" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/manager" ) func run() error { restConfig := config.GetConfigOrDie() shardLease, err := shardlease.NewResourceLock(restConfig, shardlease.Options{ ControllerRingName: "my-controllerring", }) if err != nil { return err } mgr, err := manager.New(restConfig, manager.Options{ // SHARD LEASE // Use manager's leader election mechanism for maintaining the shard lease. // With this, controllers will only run as long as manager holds the shard lease. // After graceful termination, the shard lease will be released. LeaderElection: true, LeaderElectionResourceLockInterface: shardLease, LeaderElectionReleaseOnCancel: true, // other options ... }) if err != nil { return err } // add controllers and start manager as usual ... return nil } ``` Note that if you're using controller-runtime, the same manager instance cannot run sharded and non-sharded controllers as a manager can only run under a single resource lock (either leader election or shard lease). ### Filtered Watch Cache In short: use the following label selector on watches for all sharded resources listed in the `ControllerRing`. ```text shard.alpha.sharding.timebertt.dev/my-controllerring: my-operator-565df55f4b-5vwpj ``` The sharder assigns all sharded objects by adding a shard label that is specific to the `ControllerRing` (resources could be part of multiple `ControllerRings`). The shard label's key consists of the `shard.alpha.sharding.timebertt.dev/` prefix followed by the `ControllerRing` name. As the key part after the `/` must not exceed 63 characters, the `ControllerRing` name must not be longer than 63 characters. The shard label's value is the name of the shard, i.e., the name of the shard lease and the shard lease's `holderIdentity`. Once you have determined the shard label key for your `ControllerRing`, use it as a selector on all watches that your controller starts for any of the sharded resources. With this, the shard will only cache the objects assigned to it and the controllers will only reconcile these objects. Note that when you use a label or field selector on a watch connection and the label or field changes so that the selector doesn't match anymore, the API server will emit a `DELETE` watch event. In controller-runtime, you can configure your shard to only watch and reconcile assigned objects as follows. This snippet works with controller-runtime v0.16 and v0.17, other versions might require deviating configuration. ```go package main import ( shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "k8s.io/apimachinery/pkg/labels" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/manager" ) func run() error { // ... mgr, err := manager.New(restConfig, manager.Options{ // FILTERED WATCH CACHE Cache: cache.Options{ // Configure cache to only watch objects that are assigned to this shard. // This controller only watches sharded objects, so we can configure the label selector on the cache's global level. // If your controller watches sharded objects as well as non-sharded objects, use cache.Options.ByObject to configure // the label selector on object level. DefaultLabelSelector: labels.SelectorFromSet(labels.Set{ shardingv1alpha1.LabelShard("my-controllerring"): shardLease.Identity(), }), }, // other options ... }) // ... } ``` ### Acknowledge Drain Operations In short: ensure your sharded controller acknowledges drain operations. When the drain label like this is added by the sharder, the controller needs to remove both the shard and the drain label and stop reconciling the object. ```text drain.alpha.sharding.timebertt.dev/my-controllerring ``` When the sharder needs to move an object from an available shard to another shard for rebalancing, it first adds the drain label to instruct the currently responsible shard to stop reconciling the object. The shard needs to acknowledge this operation, as the sharder must prevent concurrent reconciliations of the same object in multiple shards. The drain label's key is specific to the `ControllerRing` and follows the same pattern as the shard label (see above). The drain label's value is irrelevant, only the presence of the label is relevant. Apart from changing the controller's business logic to first check the drain label, also ensure that the watch event filtering logic (predicates) always reacts on events with the drain label set independent of the controller's actual predicates. In controller-runtime, you can reuse the helpers for constructing correct predicates and a wrapping reconciler that correctly implements the drain operation as follows: ```go package controller import ( shardcontroller "github.com/timebertt/kubernetes-controller-sharding/pkg/shard/controller" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/manager" ) // AddToManager adds a controller to the manager. // shardName must match the shard lease's name/identity. func (r *Reconciler) AddToManager(mgr manager.Manager, controllerRingName, shardName string) error { // ACKNOWLEDGE DRAIN OPERATIONS // Use the shardcontroller package as helpers for: // - a predicate that triggers when the drain label is present (even if the actual predicates don't trigger) // - wrapping the actual reconciler a reconciler that handles the drain operation for us return builder.ControllerManagedBy(mgr). For(&corev1.Secret{}, builder.WithPredicates(shardcontroller.Predicate(controllerRingName, shardName, MySecretPredicate()))). Owns(&corev1.ConfigMap{}, builder.WithPredicates(MyConfigMapPredicate())). Complete( shardcontroller.NewShardedReconciler(mgr). For(&corev1.Secret{}). // must match the kind in For() above InControllerRing(controllerRingName). WithShardName(shardName). MustBuild(r), ) } ``` ================================================ FILE: docs/installation.md ================================================ # Install the Sharding Components This guide walks you through installing the sharding components from this repository in your cluster. This procedure is independent of the controller that you want to use sharding for. ## Main Components (required) For now, only [kustomize](https://kustomize.io/) is supported as the deployment tool. All deployment manifests for this repository's components are located in [`config`](../config) and can be used from there. The `config/default` variant holds the default configuration for the sharding components. It requires [cert-manager](https://cert-manager.io/) to be installed in the cluster for managing the webhook certificates. Apply it using `kubectl`: ```bash kubectl apply --server-side -k "https://github.com/timebertt/kubernetes-controller-sharding//config/default?ref=main" ``` You can customize the configuration using the usual kustomize mechanisms: ```bash cat >kustomization.yaml < Exporting logs of kind cluster '$cluster_name'" kind export logs "$ARTIFACTS" --name "$cluster_name" || true echo "> Exporting events of kind cluster '$cluster_name'" export_events } export_events() { local dir="$ARTIFACTS/events" mkdir -p "$dir" while IFS= read -r namespace; do kubectl -n "$namespace" get event --sort-by=lastTimestamp >"$dir/$namespace.log" 2>&1 || true done < <(kubectl get ns -oname | cut -d/ -f2) } ================================================ FILE: hack/ci-e2e-kind.sh ================================================ #!/usr/bin/env bash set -o nounset set -o pipefail set -o errexit source "$(dirname "$0")/ci-common.sh" # test setup make kind-up export KUBECONFIG=$PWD/hack/kind_kubeconfig.yaml # export all container logs and events after test execution trap '{ export_artifacts make kind-down }' EXIT # deploy and test make up SKAFFOLD_TAIL=false make test-e2e GINKGO_FLAGS="--github-output" ================================================ FILE: hack/config/README.md ================================================ # dev This directory hosts manifests of components for the development setup. Manifests of the sharding components are contained in [`config`](../../config). I.e., this directory should host only "internal" manifests that are not supposed to be reused outside of this repository. ================================================ FILE: hack/config/cert-manager/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - https://github.com/cert-manager/cert-manager/releases/download/v1.19.3/cert-manager.yaml patches: # lower the webhook timeouts to make the webhooks compliant with gardener's requirements - path: patch-validatingwebhook.yaml - path: patch-mutatingwebhook.yaml ================================================ FILE: hack/config/cert-manager/patch-mutatingwebhook.yaml ================================================ apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: name: cert-manager-webhook webhooks: - name: webhook.cert-manager.io timeoutSeconds: 15 ================================================ FILE: hack/config/cert-manager/patch-validatingwebhook.yaml ================================================ apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: cert-manager-webhook webhooks: - name: webhook.cert-manager.io timeoutSeconds: 15 ================================================ FILE: hack/config/cert-manager/resources/cluster-issuer.yaml ================================================ apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-http01 spec: acme: email: null@timebertt.dev server: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: name: http01-timebertt-dev solvers: - http01: ingress: ingressClassName: nginx ================================================ FILE: hack/config/cert-manager/resources/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - cluster-issuer.yaml ================================================ FILE: hack/config/certificates/host/config.json ================================================ { "signing": { "default": { "expiry": "43800h" }, "profiles": { "server": { "usages": [ "signing", "key encipherment", "server auth" ], "expiry": "43800h" } } } } ================================================ FILE: hack/config/certificates/host/generate.sh ================================================ #!/usr/bin/env bash if ! command -v cfssl &>/dev/null ; then echo "cfssl not found, install it from https://github.com/cloudflare/cfssl" exit 1 fi cd "$(dirname "$0")" rm -f *.pem cfssl gencert -config config.json -initca webhook-ca.json | cfssljson -bare webhook-ca cfssl gencert -config config.json -ca=webhook-ca.pem -ca-key=webhook-ca-key.pem -profile=server webhook-server.json | cfssljson -bare webhook-server rm *.csr ================================================ FILE: hack/config/certificates/host/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: sharding-system generatorOptions: disableNameSuffixHash: true secretGenerator: - name: webhook-ca options: annotations: cert-manager.io/allow-direct-injection: "true" files: - ca.crt=webhook-ca.pem ================================================ FILE: hack/config/certificates/host/webhook-ca-key.pem ================================================ -----BEGIN RSA PRIVATE KEY----- MIIJKQIBAAKCAgEAsYRPd2BqRLB8TX/5bWZgZzRHihzB49P3t88lkfzbkinOFSWr IkQNnC1LOmCim39S0Un6ucEcyIZVDpCHvWyn7+YTmph+hWqccUNS+cmC3S9rt021 /Ejg7/Lw7s7vNyxe4WsWSZWfx1+6aanUSNklvhDJ4fvveJx3qfKW+5sgdmVKXZk4 7EcmFVMpY64y9yyju6KvaZd8M4YO7DvkfcLVnuXUWjFTzU8nNFvO8XoyLmRAcNOb A3Tf1Zy+HmJmnZo3hwgVOms2HRqRgbsOVYUOH67i2salfieDEN6KSTyieAbYvxIt R8VlhmcLjDlCFCdk0m3em6b8nroCw7wMUHCjJxvpDpkj4qEq6j+SZe/rSXCoRnyn uRBAFaCvqmpuep/djx3THF2wlS0TFCglubhmdxFxXYFhxKQDh5upvxWObBQb9X/F Yr/rQlwez/v0G9LgxAVp1b96pnU4qE6xRmWkaRVrK7cbubLraqQ2S4XF8/mmoZZN fAqMbd+LJucUlBHdT0Q2QmmkxysLNbnlfMEplVXU0eA8LFa43raRLh8Z7mhiuSC+ WhTI5UCF2OxIqFVgE0kYi3PA+pT8DcOb2KzytAZpHsBOTwwHoHjsyYpxYpsIvPhN SuWdv9AjOC7nmDzfM8N9WDPelg8tXC8XX330RbI5457Naj1HImZvTZd1TocCAwEA AQKCAgEAhQLQ0HAL8GAVI7TqXlDBl1MS76fQmDdxe+bZDeRbWc+9PRc2fbxkPkup /Jn//WeP1IYMOjc6q/4LqZgePY823oiU09fDpZBWnH+HouadCcLIgVbXL6wj72cn pKilkb/LcDhfQM++IxPVh+rax6L9psbJnmy56LPE7jB5dRmtX0lSSYPPpStCm+Pu NWSHh7GJFcU2jnYVeD3Q3K2b7aeZjTBExzgCxOm0RIUuML4Q77Xqmx/THOnr9hE2 W2n73cd6J9GkpltC9te7g2t3uBi0loTiMm95/Wb5zCATmgC29BydN74U85wzEFwR yQX2P0etQgdVL2gWDZDvFV7IE1XyyNDMB0fX357CmoFPC8HceKzIbE6sfRqawyXI T+Jj910uf7Sep37BOFdOTbJW42nuMtdnAnSPJYb0xu8pAGlamffj64Mh65WA/HLX ilWemp7ymrSVkHgmgQ09dXw/5xlTFgrO7wOEArK97FRQCg75zKxxGHR59AKnpcQe RKfmhHEHyJXPP3xEdq50G26xlbEAE45eXx1qsdPWZK3jKmUZhZvu6PuO42x7qU2I Lz4HY2HRH4XGXmnbW6GQc88AJEys1b/83CYIKEgaXsxa6x5TB3hT0YnzCgffZ4xm vspLiQ8oVcAAgXQ68IWAZFP1+3ZFgBW2ZJfbOBFFP6FchXH4UfECggEBAMYdG3y7 wu92E6/XQLSUaj8jFlljKrAjmBbp2+V7FLzXoQozgIOtGS3A47JALkY5D+k2rhEt tQ+3R3k33YTZ5PoS9r1fGArtMqupUtsyrNAWz4e4GBwZDW8T89QC9enXMNiFg8kz RwebxKYz+oiqBn/Bq8UrbppsHUTmeMOODjXUq2X6CL+BD5+vgfav1bOQIZ2yotYF R3B5s0qag1OlNpbFIX7r1blHNXGrvVHhwC527HObslmp8efZL5wg3P/aDQ6NQN08 kpmEVbq3ruPfqNut3yuUOW0hr+S+5q66ik+qxN406/zAHtpbuea4Jh5rJibjv9PT za8nPUJP/i1QeRMCggEBAOVijxdIBg1igSYNF3F+NTx2WHYiA7rFDkENGrZEvwmE q0Ifml0cmzjEbSjqUkC3ZzDE7hUexQeiJNv+a86vXBm+aFpLcKbZ6cJEb86vL6bf oiW2+CcdMbMQHpR9UEdzGNLYR6DnTMaQA/w2umJXCXBFoR1pHdCSi2kLaw3lHBCf mzdfIvgDxqBqXMKhfbWUrH/Pc+hUXPejCqkS2SuL2b/N91V1uiaQ47xeXOxvDY5D 6B/u1Cia0O6NGHDXSrmczhAg3jyhc8ttDuGQnpyHH3tA1RLxHu0oxLxN+o9K6JtW 9fUxOgzJIcJtAmbuIbbcwxuSueabJgZoSp5JtdSxVz0CggEACiLJGjudAJVg8nkn 1VVWjj5kUVRyhap8iIeUeYwvhm3dzmDOLW54wE+DFsaT14Hp33utsjFNdy1gWcJS 8g4X2feIai3oU/7IveGe3JoeH1NbcM0pZp6dglZZ/jncjQc2d411LaES/D+q8vnr 0nwocvbcq+zJ7tqjMLg963tkHLrxvfjp46pdu0TGeHGMlHBGWAQgsqR4gDepxaJc H7ZvMY2KZiz4tU8AW/12ZS8Qnw/0jwGjQVUhjEQfXHSN+gUU7+6oJ+mGcpZDsJbf Osdho0OlDFy8B2pWznQ55yyiEOtiwR+iBz9pFLDmtPgs8xd2Tz0Nvm+ysUhnqPHg xj68wwKCAQA7MYPbbiqhqZnKR/aUwwzZ3XBWi9CKke9rugX6oyLpQeMv3Rfoj0k/ DPFebZlsOefXHfqSWK5fmegJHU6Ut4v82LX1FyKq6/D2wNJZc7vIRE2DjgPblB0P KEm759qflYQCZO2XCBk35FIi87yFRBCbeFxrSoT3Hdn78YZev5DOeWGEmHhdqBvJ qajmUOYvxX3+PXqbqamT/e7yUnrYUe6PIIeC9i5jZWBfa7pvCPlmjP+JvgfhspHX /XEhLW2LGHvUjabL3p4TEMGWU8uaeQQWulRB3xcr/ClIrpbKA3qjG329GEbypbSg h6DnDuyEU9PFecefSso1PRSEZGEX0evBAoIBAQC8MdTBttGMsLWvnD0HsV473yTj jo0lyLSSEsTqnYla/7Ia1pqV4d18fPufV/vnz8Dy6ZyGrtmSAsQrZbEbRVBLW1kD ilfL/ThQfsBHVxtRGpFB4kpPHJlyNETUD7HDwnuqIS/iODgltZXQAqRjN5ZcaHMd F4nT9Ua/Emwv8H/ibC16yBaJQ2jfDa4pD+gLnxtHblFeDPfu5fOiZL5Zm8ksh3u3 uiHiPmyPKPT/aYRwyynvyJVdhWWI2nG+MhqdAIQzdmj7IEvLsyHuo/Mz2J+dOTrh +xNR37kYcH7RWwzxCBk4Wzx4prZ1e7UD82whBxYnUodJuJYu3PjKztC2LBpC -----END RSA PRIVATE KEY----- ================================================ FILE: hack/config/certificates/host/webhook-ca.json ================================================ { "CN": "sharding:sharder", "key": { "algo": "rsa", "size": 4096 } } ================================================ FILE: hack/config/certificates/host/webhook-ca.pem ================================================ -----BEGIN CERTIFICATE----- MIIFBjCCAu6gAwIBAgIUel12x8tnTJwEPcuKhb8gxDzNL8UwDQYJKoZIhvcNAQEN BQAwGzEZMBcGA1UEAxMQc2hhcmRpbmc6c2hhcmRlcjAeFw0yMzExMTAxMzA3MDBa Fw0yODExMDgxMzA3MDBaMBsxGTAXBgNVBAMTEHNoYXJkaW5nOnNoYXJkZXIwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCxhE93YGpEsHxNf/ltZmBnNEeK HMHj0/e3zyWR/NuSKc4VJasiRA2cLUs6YKKbf1LRSfq5wRzIhlUOkIe9bKfv5hOa mH6FapxxQ1L5yYLdL2u3TbX8SODv8vDuzu83LF7haxZJlZ/HX7ppqdRI2SW+EMnh ++94nHep8pb7myB2ZUpdmTjsRyYVUyljrjL3LKO7oq9pl3wzhg7sO+R9wtWe5dRa MVPNTyc0W87xejIuZEBw05sDdN/VnL4eYmadmjeHCBU6azYdGpGBuw5VhQ4fruLa xqV+J4MQ3opJPKJ4Bti/Ei1HxWWGZwuMOUIUJ2TSbd6bpvyeugLDvAxQcKMnG+kO mSPioSrqP5Jl7+tJcKhGfKe5EEAVoK+qam56n92PHdMcXbCVLRMUKCW5uGZ3EXFd gWHEpAOHm6m/FY5sFBv1f8Viv+tCXB7P+/Qb0uDEBWnVv3qmdTioTrFGZaRpFWsr txu5sutqpDZLhcXz+aahlk18Coxt34sm5xSUEd1PRDZCaaTHKws1ueV8wSmVVdTR 4DwsVrjetpEuHxnuaGK5IL5aFMjlQIXY7EioVWATSRiLc8D6lPwNw5vYrPK0Bmke wE5PDAegeOzJinFimwi8+E1K5Z2/0CM4LueYPN8zw31YM96WDy1cLxdfffRFsjnj ns1qPUciZm9Nl3VOhwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQUIPap7bhHigezp3QQ6oB1q9+rAzYwDQYJKoZIhvcN AQENBQADggIBAIzWfFXq8kmge+Bx+0L9zMb2a7vKsm8fX92/e3HwjCBg5uxwlebR gaQeK00O0+y0ozUaQ2fdxwQxH2i/hMEykvhpoAkPoMasirNVQ/FO7dF4cJ2NGwC0 xsVWS+GmoUtNfU+AACitFVnbqRc9mYgb5xYEz+3AMvvsto3CHEVvRAKzWAmRW0wV M2dwq43Tri3UJ93SxsqIzKsOkWlfZV+2PBB6gxBdvSfLlZbo4TlIUwUdYBCUucBt e8i4g5SkYuLlBfRdtvDA5NKKsfxpqNAmHnpfUWyHkRyHngV6zB2xtRJ2K4VYGHDE mj02gj3Xb3HonCZuCLVXTAMAvLNUxpaQ7QjhCvMBwVOwQyiaAy2oy/EIqq90vaOF y07GKu/xl70B6mw7+T73YwlqphBnqdWY/u10VkqVRa1xBvhIgR7ISdjVWq5l2tYy w7PU1JEXPpJe5e54DQlkF6KFN3qLvwwKh34jtuElbxCrZ4Jft3GTR9eN7AEY5RUf Q7idZjQne1VX664kANnuFcEuTWyyDVJMsNBQXLcKMFFtigANaW57Ev15f7Z89Lom TOShtPrnGEUNYf44Xj28iMiae7RmRC/MhMIQGkOij+CmjuedpbkxZlFq6Y0ErHt1 OKEdbfGvK/ffTMvuMk8zjEvXJXrTIYxqYsxow0LraaenDGLnNRy+OjH6 -----END CERTIFICATE----- ================================================ FILE: hack/config/certificates/host/webhook-server-key.pem ================================================ -----BEGIN RSA PRIVATE KEY----- MIIJKAIBAAKCAgEAnDCsNJ5AoV5lrrsOAtzvDn7tZsqqM0e68p6UGPijBcmPS1Qj VRsbHyjWnd/L3bAJSOu7pwu3gkr3HLyPrrrRLobCzMnAVt1+X4qJnIdGYuOZVJfg Lgmyeh8eWgeVyxAbObXkQ19LztDDrayMc8IyRyCQzSoZ6OJUWbTfHkJSQRvxowUt OvOF1zgg5qmLL5jiQNXSfpmWwqhXdmcuHNtlau0jhma2HXBPkVEidQvPRiaMYBNb oHTzjAFw3R72mHmvOHhC0hdkF5q2A4CC9TvnIdf6fQZY5zZrWMWvrEvJBqX3k6jz QbwD3EnE5MJh56WIMESdo69xeeJZwaprmDr8Qf56uJqHcNwIqHPpusKu2Jceh5A+ pXo0OnBic6/sThCEvJ1luudTa7zKGiOaBlkVJ6PDD+v56j7/SXIx8jIdtgBStcX9 eUDnUHgNVSmrOzns5pn0EsYXni6UdHYtGsnSrAqLs967vsHw2U3if7EyoxbE4jdn GCJwUmDADu67CKGH0gopxn71ymAiV51oSO6IC7qFnurWwCyXLCvKN4KEFpQERKX6 iSflz7XKka604qXKXUGB8obq19+8MlVHOtq1OCtbYIDZmueBYZglp7p6yAVIinqw kimkmvCRrzn2B5YssoVSmWJCvoC7a6+9rYK+63nXHNRtZzf9istGPSJjRUUCAwEA AQKCAgA8mTnG9HtY4HoND/AAtl1dv2s2TX05hiQHS/VjttvxO+GHtW4779dXAI48 FH9RVKJVk3hr+ETLnXBAyvvoK/1K0ugzcjdYvHjycpqvi2CIr4tm4cINup9veDFb dsPsVCRsAKE+bnPIGwFAmciohPji1cS4hRQmYeGeKGnEoLCvKDtZJ4ID9EXCWbmS JMemwOdPhmYzzj1K6ut8Oc4PTiQMF1OIKsOPqmqEk/kNdnaF3iDqibgsChQQBuMW N5QvVk7gVvB9+KtR6SmjNDIbGZG0dMpvxY2qr1d4ysI80+570Nq8hHlU0LCiwFBO /QflSzkKmSScRE5/no16cTdrib8i9HWT/ejlAfhN/FpD8jeccU26UPaoKyGQgvHV YceIt/o8NQQYO9/Vwc+8kKFAyjyI5jaW1Cjdp0ImZ7MK40yKYpFw3EHCChlOBh97 B6IEhGAyqU93ADUxJZ/KeEG4cxSPzZtjGBrSMTbWyLUAYeUI8miVWMd2NvacLUs9 PPil4jgLl9lhpG81BHe1YvQ+PKaKLoQWmaIPAe3Wb5aKnwX++nbowrNLYETHCQ/J wklZmk+2A+oPjEkrp8GoTyAcD9cJAXHxH9/6itdUhtA9lxAKKlpZNNMlMLWbzEJn /LOof/2ob3aws/6y3ETNbDen/cVjyk6gG9gO97AYUP++zxmMZQKCAQEAwwkgR2VO 2UghqEQPigMhxy3VVKfhOp9ebS7bYvtZNstEE9WOTUDdQudTk0BFE4HL/3KbghLI RcSEUtZxYJQSfXu4EHtEg/EDYaoPnWhcDxj1Tn4O4m58tTEkMT/42AzPlnAESoAB 5LO6SV/sBtXP+CLmga1Y43Op2aimM1ewjJWqJl9IYTVp8bDZqU66JelJT8GHZ6tY pfgAKSWyz+RX8hdtuuwxBNcktdJgeuH6zO4EwgCyzd5xrMyG1J8AM557ReiRntkP Sbhq9THQFfMJld7Guo7YNTX6BhYyl04821THHd+oCITw7OY23aH0oJgIE9cllzBZ KkwWOw5XubX7vwKCAQEAzQMalIGZTFilHSKj7/QqyW8+xo7urV211uYRV6eLnTx2 1+jcbizWfH0N8Uwt1Jvk8TWDIrwndZoeIrINXWiZPZf1+EDkRAgMwinfS7bsrLVd lNsQoPAWMydoZEvgM7+mfLbjPkX2wUy03WNI0htk4+uxnZMD75y/r2ZRKRxV7bi4 NMS6kQrGYjaivtqMz7hqHBd0O1PUyMpcMREMuKiawWYjERKIJU+dI0empTWAyLVb 5Q93IkMjxVKEa65jjLB/ngvloNxjCK28WelG5Dbdc2zUa+OQ8GguD6Q1p5UQNoHv KIMuS6mJm8UUl746cdbPv6lgYAByfBat6PKE6xrP+wKCAQBLAxmNHCPFYf6/7t1j IW0+ZBxmoOL5Xw48RAdQ/IcFkgwu7LX8dHQlJT95pQBsTkGdkADLeFnaq4iRK7UT hh/Ob2UNwbtKW8oHKBc1XUv66oh+lfE3mXMRZUMcRhR5VAQLQi4EUVNpGM8PJXtr 7ZQ9RX8OZROI95VeB4VUvedDStTUSVVXPenvcStl+MeTiTQPHsnrT3Wa79Vv/fXW C2bfz67+c5Uu3WhbHfzJhlylsO3Xh9k9YM6rvUYmRLkZIV0cOCS5yZYdrnZEs9Hq fz0yjSo12nbBkG8HJEZ09zxkxyiGDt1b2XWoR6rWd1HU6mRA7UCh85B3uifastt+ q8WVAoIBAQCxAWUJo3vANykYJrh0jNQEZ1BED1Rzyt0dVjbS/43DjFjvwdXQKlZl 1XMcSzGmx5K70AARFXLcTtyGCEURySXF0FZGqYBsXKbnXU+2B5IA6/aIdzu8OI5y TCwNrJU/GNGeDCnXsoCCFMB0BSzye0R4pR8NdcmIMEYwIp8gZ56pSTuCE/khEbSH R7TsI7ZAAnFbH8TzFEY7trwygQ4CwVAcexr7uoxh6oM52rs/GRrAMBXPh7LMmjtg OwaqEj9RUXJd+tegM6gt7hMZbhgPIm/BIM2m+SxC5TAfwR+yOTluVnEvAVQPb6mo HFjTSyMa9uUYDh1vxfMSwGIXJo0skFHRAoIBAEEX7v0NaSZX2m7WY/prxGqIQ/MD Itf6Rdspl/CdeU7xHezzCKGgLdvlZKM24XnZZO/leZG/H/BKPkKoPG4k/QxsZb3B S1WJD1DineQyjw4GsLgMaOT7rYWVrdypDKcuwVU+drsoED5P19Wr2GnetnzoYEYw LjSaoCDvfwPszesS8qnA/YjfKbF9PSANbaj/fK/Z8w1ZS2mVF52arKiAbpYJgK7H Y4EfYHcZjk4vJOMZOlgio/6H0CyLvc2pAfXLVN0Ho0RtTy0KgwXsxCx2gw+BU5xK B9tKU0Q+8sWmjUaoj3IGxKjGkJG/a8M9H3jAVnd8NpI9A0if5LXVHTlfXfo= -----END RSA PRIVATE KEY----- ================================================ FILE: hack/config/certificates/host/webhook-server.json ================================================ { "CN": "sharding:sharder:webhook", "key": { "algo": "rsa", "size": 4096 }, "hosts": [ "localhost", "host.docker.internal", "sharder.sharding-system", "sharder.sharding-system.svc", "sharder.sharding-system.svc.cluster.local" ] } ================================================ FILE: hack/config/certificates/host/webhook-server.pem ================================================ -----BEGIN CERTIFICATE----- MIIF1TCCA72gAwIBAgIURVQwgiERbtUeNjwxwSrp4jIAY+UwDQYJKoZIhvcNAQEN BQAwGzEZMBcGA1UEAxMQc2hhcmRpbmc6c2hhcmRlcjAeFw0yMzExMTAxMzA3MDBa Fw0yODExMDgxMzA3MDBaMCMxITAfBgNVBAMTGHNoYXJkaW5nOnNoYXJkZXI6d2Vi aG9vazCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJwwrDSeQKFeZa67 DgLc7w5+7WbKqjNHuvKelBj4owXJj0tUI1UbGx8o1p3fy92wCUjru6cLt4JK9xy8 j6660S6GwszJwFbdfl+KiZyHRmLjmVSX4C4JsnofHloHlcsQGzm15ENfS87Qw62s jHPCMkcgkM0qGejiVFm03x5CUkEb8aMFLTrzhdc4IOapiy+Y4kDV0n6ZlsKoV3Zn LhzbZWrtI4Zmth1wT5FRInULz0YmjGATW6B084wBcN0e9ph5rzh4QtIXZBeatgOA gvU75yHX+n0GWOc2a1jFr6xLyQal95Oo80G8A9xJxOTCYeeliDBEnaOvcXniWcGq a5g6/EH+eriah3DcCKhz6brCrtiXHoeQPqV6NDpwYnOv7E4QhLydZbrnU2u8yhoj mgZZFSejww/r+eo+/0lyMfIyHbYAUrXF/XlA51B4DVUpqzs57OaZ9BLGF54ulHR2 LRrJ0qwKi7Peu77B8NlN4n+xMqMWxOI3ZxgicFJgwA7uuwihh9IKKcZ+9cpgIled aEjuiAu6hZ7q1sAslywryjeChBaUBESl+okn5c+1ypGutOKlyl1BgfKG6tffvDJV RzratTgrW2CA2ZrngWGYJae6esgFSIp6sJIppJrwka859geWLLKFUpliQr6Au2uv va2Cvut51xzUbWc3/YrLRj0iY0VFAgMBAAGjggEHMIIBAzAOBgNVHQ8BAf8EBAMC BaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU Y2OhGXVByKhfKePAFNjN3oE5b6UwHwYDVR0jBBgwFoAUIPap7bhHigezp3QQ6oB1 q9+rAzYwgY0GA1UdEQSBhTCBgoIJbG9jYWxob3N0ghRob3N0LmRvY2tlci5pbnRl cm5hbIIXc2hhcmRlci5zaGFyZGluZy1zeXN0ZW2CG3NoYXJkZXIuc2hhcmRpbmct c3lzdGVtLnN2Y4Ipc2hhcmRlci5zaGFyZGluZy1zeXN0ZW0uc3ZjLmNsdXN0ZXIu bG9jYWwwDQYJKoZIhvcNAQENBQADggIBACya1KVsYrn2ppv4/OIHduXyyHYdB9KU qnp98zAriLcPAgn1n9PuNYpfoyCP1amvKx24oUEW4NnPED3a54AeDOdInI2j7Xmb NVgjGBAta7ye4oZTuiB+MfBgpaSlH8ML6B6j7B/LQbQLpbSp/ZFNj73o56XAr/fi KQlbnn1fmGKlNywXDOnMpYhrYKMlB0KJ+bhTlD8gueBhYTRH4O5Kw1n6T2XUiZNf nK+rXMdCnXgq6HWWsRlOWWXFsxcDK58sEzw+uhQD/9Yu5jpcJV13K/MEK3q4L5pP 4NDq7zItfF5GgKl9AZwXKTSJ8Ij3bjgb1HJteaM9Ul+Gu2NWd1BooQi7RBbtPOjN noi1JL2tJELG4bl7vUPvP+l/005cgCdqwPch4Eq+am3i0AT4rPutWnFlcZfc4lHm JMku6EvtS6aMQeipQmG91tHumtgNAcN5YlkHrDqL2FiOHYAo/XXjwrH3rL27s2CT OfpGcBS4wJsMUabdqPpU0mAXKcWFFwlv4e8hNiB8JF6ty8weN5AYymCAE/66mZgI SQ/0FYmSRFLg5g51bPHEEUig3UsI68pxJW3DQQSOYmHwpRPMHYV8lI8CrrAHtPp8 eN8f8jBVkJfDLZ/LpeE6mH0OmtEbA+29kfYt1pdWdTAqrcmaF3d5j9wF28mExMXw d92Evgc96uZh -----END CERTIFICATE----- ================================================ FILE: hack/config/checksum-controller/controller/deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: checksum-controller spec: replicas: 3 template: spec: automountServiceAccountToken: true securityContext: runAsNonRoot: true containers: - name: checksum-controller image: checksum-controller:latest args: - --zap-devel env: - name: DISABLE_HTTP2 value: "true" securityContext: allowPrivilegeEscalation: false resources: requests: cpu: 25m memory: 50Mi serviceAccountName: checksum-controller terminationGracePeriodSeconds: 10 ================================================ FILE: hack/config/checksum-controller/controller/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: default labels: - includeSelectors: true pairs: app.kubernetes.io/name: controller-sharding app.kubernetes.io/component: checksum-controller images: - name: checksum-controller newName: ghcr.io/timebertt/kubernetes-controller-sharding/checksum-controller newTag: latest resources: - ../controllerring - deployment.yaml - rbac.yaml - serviceaccount.yaml ================================================ FILE: hack/config/checksum-controller/controller/rbac.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: sharding:checksum-controller rules: - apiGroups: - coordination.k8s.io resources: - leases verbs: - get - create - update - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - "" resources: - secrets verbs: - get - list - watch - patch - apiGroups: - "" resources: - configmaps verbs: - get - list - watch - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: sharding:checksum-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: sharding:checksum-controller subjects: - kind: ServiceAccount name: checksum-controller ================================================ FILE: hack/config/checksum-controller/controller/serviceaccount.yaml ================================================ apiVersion: v1 kind: ServiceAccount metadata: name: checksum-controller automountServiceAccountToken: false ================================================ FILE: hack/config/checksum-controller/controllerring/controllerring.yaml ================================================ apiVersion: sharding.timebertt.dev/v1alpha1 kind: ControllerRing metadata: name: checksum-controller spec: resources: - group: "" resource: secrets controlledResources: - group: "" resource: configmaps namespaceSelector: matchLabels: kubernetes.io/metadata.name: default ================================================ FILE: hack/config/checksum-controller/controllerring/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - controllerring.yaml - sharder_rbac.yaml ================================================ FILE: hack/config/checksum-controller/controllerring/sharder_rbac.yaml ================================================ # These manifests grant the sharder controller permissions to act on resources that we listed in the ControllerRing. # We need to grant these permissions explicitly depending on what we configured. Otherwise, the sharder would require # cluster-admin access. --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: sharding:controllerring:checksum-controller rules: - apiGroups: - "" resources: - configmaps - secrets verbs: - list - patch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: sharding:controllerring:checksum-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: sharding:controllerring:checksum-controller subjects: - kind: ServiceAccount name: sharder namespace: sharding-system ================================================ FILE: hack/config/external-dns/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: external-dns images: - name: registry.k8s.io/external-dns/external-dns newTag: v0.19.0 resources: - namespace.yaml - https://github.com/kubernetes-sigs/external-dns//kustomize?ref=v0.19.0 patches: - path: patch-deployment.yaml # Add permissions for endpointslices needed for https://github.com/kubernetes-sigs/external-dns/pull/5493. # TODO: drop this patch once https://github.com/kubernetes-sigs/external-dns/pull/5573 has been released. - target: kind: ClusterRole name: external-dns patch: | - op: add path: /rules/- value: apiGroups: ["discovery.k8s.io"] resources: ["endpointslices"] verbs: ["get","watch","list"] ================================================ FILE: hack/config/external-dns/namespace.yaml ================================================ apiVersion: v1 kind: Namespace metadata: name: external-dns ================================================ FILE: hack/config/external-dns/patch-deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: external-dns namespace: default spec: template: spec: containers: - name: external-dns args: - --source=ingress - --source=service - --domain-filter=timebertt.dev - --provider=google - --log-format=json - --google-project=$(GOOGLE_PROJECT) - --google-zone-visibility=public - --policy=sync - --registry=txt - --txt-owner-id=shoot--ixywdlfvei--sharding-2025a5e1-9ac9-471c-9ef0-0a2e70527e5f-ske - --interval=1m # ensure the records are not owned by short-lived acme solvers managed by cert-manager or website ingresses - --label-filter=acme.cert-manager.io/http01-solver!=true,app!=website env: - name: GOOGLE_APPLICATION_CREDENTIALS value: /etc/secrets/service-account/service-account.json - name: GOOGLE_PROJECT valueFrom: secretKeyRef: name: google-clouddns-timebertt-dev key: project volumeMounts: - name: clouddns-credentials mountPath: /etc/secrets/service-account readOnly: true volumes: - name: clouddns-credentials secret: secretName: google-clouddns-timebertt-dev ================================================ FILE: hack/config/ingress-nginx/default/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: ingress-nginx resources: - https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.14.3/deploy/static/provider/cloud/deploy.yaml patches: - path: patch_default_ingress_class.yaml - path: patch_controller_resources.yaml # Delete validation webhook for Ingresses. # We don't need or want validation for Ingress objects in the development and load testing setup. It results in high # latency for API requests and CPU waste during load tests. - patch: | apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: ingress-nginx-admission $patch: delete # This job fails if the ValidatingWebhookConfiguration does not exist. Drop it as well. # Note: we can't drop the ingress-nginx-admission-create job, which creates the webhook certificate. Without this, # the ingress-nginx-controller won't start. - patch: | apiVersion: batch/v1 kind: Job metadata: name: ingress-nginx-admission-patch namespace: ingress-nginx $patch: delete ================================================ FILE: hack/config/ingress-nginx/default/patch_controller_resources.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: ingress-nginx-controller namespace: ingress-nginx spec: template: spec: containers: - name: controller resources: requests: cpu: 10m memory: 256Mi ================================================ FILE: hack/config/ingress-nginx/default/patch_default_ingress_class.yaml ================================================ apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: nginx namespace: ingress-nginx annotations: ingressclass.kubernetes.io/is-default-class: "true" ================================================ FILE: hack/config/ingress-nginx/kind/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../default patches: - path: patch_service_nodeport.yaml ================================================ FILE: hack/config/ingress-nginx/kind/patch_service_nodeport.yaml ================================================ apiVersion: v1 kind: Service metadata: name: ingress-nginx-controller namespace: ingress-nginx spec: ports: - appProtocol: http name: http nodePort: 30888 port: 80 protocol: TCP targetPort: http ================================================ FILE: hack/config/ingress-nginx/shoot/certificate.yaml ================================================ apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: webhosting-tls spec: dnsNames: - webhosting.timebertt.dev issuerRef: group: cert-manager.io kind: ClusterIssuer name: letsencrypt-http01 secretName: webhosting-tls usages: - digital signature - key encipherment ================================================ FILE: hack/config/ingress-nginx/shoot/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: ingress-nginx resources: - ../default - certificate.yaml patches: - path: patch_service.yaml - target: group: apps version: v1 kind: Deployment name: ingress-nginx-controller namespace: ingress-nginx patch: | - op: add path: /spec/template/spec/containers/0/args/- value: "--default-ssl-certificate=ingress-nginx/webhosting-tls" ================================================ FILE: hack/config/ingress-nginx/shoot/patch_service.yaml ================================================ apiVersion: v1 kind: Service metadata: name: ingress-nginx-controller namespace: ingress-nginx annotations: external-dns.alpha.kubernetes.io/hostname: webhosting.timebertt.dev ================================================ FILE: hack/config/kind-config.yaml ================================================ apiVersion: kind.x-k8s.io/v1alpha4 kind: Cluster nodes: - role: control-plane extraPortMappings: # ingress-nginx - containerPort: 30888 hostPort: 8088 kubeadmConfigPatches: - | apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration maxPods: 250 - | apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration controllerManager: extraArgs: kube-api-qps: "800" kube-api-burst: "1000" ================================================ FILE: hack/config/kyverno/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - https://github.com/kyverno/kyverno/releases/download/v1.17.0/install.yaml configMapGenerator: - name: kyverno namespace: kyverno behavior: merge options: disableNameSuffixHash: true literals: # overwrite default namespaceSelector for webhook configs to exclude kube-system # the second part makes gardeners care controller/webhook remediation happy - >- webhooks={ "namespaceSelector": { "matchExpressions": [{ "key": "kubernetes.io/metadata.name", "operator": "NotIn", "values": ["kyverno", "kube-system"] }, { "key": "gardener.cloud/purpose", "operator": "NotIn", "values": ["kube-system"] }] } } ================================================ FILE: hack/config/monitoring/crds/0alertmanagerConfigCustomResourceDefinition.yaml ================================================ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 operator.prometheus.io/version: 0.85.0 name: alertmanagerconfigs.monitoring.coreos.com spec: group: monitoring.coreos.com names: categories: - prometheus-operator kind: AlertmanagerConfig listKind: AlertmanagerConfigList plural: alertmanagerconfigs shortNames: - amcfg singular: alertmanagerconfig scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: description: |- AlertmanagerConfig configures the Prometheus Alertmanager, specifying how alerts should be grouped, inhibited and notified to external systems. 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: |- AlertmanagerConfigSpec is a specification of the desired behavior of the Alertmanager configuration. By default, the Alertmanager configuration only applies to alerts for which the `namespace` label is equal to the namespace of the AlertmanagerConfig resource (see the `.spec.alertmanagerConfigMatcherStrategy` field of the Alertmanager CRD). properties: inhibitRules: description: |- List of inhibition rules. The rules will only apply to alerts matching the resource's namespace. items: description: |- InhibitRule defines an inhibition rule that allows to mute alerts when other alerts are already firing. 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 sourceMatch: description: |- Matchers for which one or more alerts have to exist for the inhibition to take effect. The operator enforces that the alert matches the resource's namespace. items: description: Matcher defines how to match on alert's labels. properties: matchType: description: |- Match operation available with AlertManager >= v0.22.0 and takes precedence over Regex (deprecated) if non-empty. enum: - '!=' - = - =~ - '!~' type: string name: description: Label to match. minLength: 1 type: string regex: description: |- Whether to match on equality (false) or regular-expression (true). Deprecated: for AlertManager >= v0.22.0, `matchType` should be used instead. type: boolean value: description: Label value to match. type: string required: - name type: object type: array targetMatch: description: |- Matchers that have to be fulfilled in the alerts to be muted. The operator enforces that the alert matches the resource's namespace. items: description: Matcher defines how to match on alert's labels. properties: matchType: description: |- Match operation available with AlertManager >= v0.22.0 and takes precedence over Regex (deprecated) if non-empty. enum: - '!=' - = - =~ - '!~' type: string name: description: Label to match. minLength: 1 type: string regex: description: |- Whether to match on equality (false) or regular-expression (true). Deprecated: for AlertManager >= v0.22.0, `matchType` should be used instead. type: boolean value: description: Label value to match. type: string required: - name type: object type: array type: object type: array muteTimeIntervals: description: List of MuteTimeInterval specifying when the routes should be muted. items: description: MuteTimeInterval specifies the periods in time when notifications will be muted properties: name: description: Name of the time interval type: string timeIntervals: description: TimeIntervals is a list of TimeInterval items: description: TimeInterval describes intervals of time properties: daysOfMonth: description: DaysOfMonth is a list of DayOfMonthRange items: description: DayOfMonthRange is an inclusive range of days of the month beginning at 1 properties: end: description: End of the inclusive range maximum: 31 minimum: -31 type: integer start: description: Start of the inclusive range maximum: 31 minimum: -31 type: integer type: object type: array months: description: Months is a list of MonthRange items: description: |- MonthRange is an inclusive range of months of the year beginning in January Months can be specified by name (e.g 'January') by numerical month (e.g '1') or as an inclusive range (e.g 'January:March', '1:3', '1:March') pattern: ^((?i)january|february|march|april|may|june|july|august|september|october|november|december|1[0-2]|[1-9])(?:((:((?i)january|february|march|april|may|june|july|august|september|october|november|december|1[0-2]|[1-9]))$)|$) type: string type: array times: description: Times is a list of TimeRange items: description: TimeRange defines a start and end time in 24hr format properties: endTime: description: EndTime is the end time in 24hr format. pattern: ^((([01][0-9])|(2[0-3])):[0-5][0-9])$|(^24:00$) type: string startTime: description: StartTime is the start time in 24hr format. pattern: ^((([01][0-9])|(2[0-3])):[0-5][0-9])$|(^24:00$) type: string type: object type: array weekdays: description: Weekdays is a list of WeekdayRange items: description: |- WeekdayRange is an inclusive range of days of the week beginning on Sunday Days can be specified by name (e.g 'Sunday') or as an inclusive range (e.g 'Monday:Friday') pattern: ^((?i)sun|mon|tues|wednes|thurs|fri|satur)day(?:((:(sun|mon|tues|wednes|thurs|fri|satur)day)$)|$) type: string type: array years: description: Years is a list of YearRange items: description: YearRange is an inclusive range of years pattern: ^2\d{3}(?::2\d{3}|$) type: string type: array type: object type: array required: - name type: object type: array receivers: description: List of receivers. items: description: Receiver defines one or more notification integrations. properties: discordConfigs: description: List of Discord configurations. items: description: |- DiscordConfig configures notifications via Discord. See https://prometheus.io/docs/alerting/latest/configuration/#discord_config properties: apiURL: description: |- The secret's key that contains the Discord webhook URL. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic avatarURL: description: The avatar url of the message sender. pattern: ^https?://.+$ type: string content: description: The template of the content's body. minLength: 1 type: string httpConfig: description: HTTP client configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object message: description: The template of the message's body. type: string sendResolved: description: Whether or not to notify about resolved alerts. type: boolean title: description: The template of the message's title. type: string username: description: The username of the message sender. minLength: 1 type: string required: - apiURL type: object type: array emailConfigs: description: List of Email configurations. items: description: EmailConfig configures notifications via Email. properties: authIdentity: description: The identity to use for authentication. type: string authPassword: description: |- The secret's key that contains the password to use for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic authSecret: description: |- The secret's key that contains the CRAM-MD5 secret. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic authUsername: description: The username to use for authentication. type: string from: description: The sender address. type: string headers: description: |- Further headers email header key/value pairs. Overrides any headers previously set by the notification implementation. items: description: KeyValue defines a (key, value) tuple. properties: key: description: Key of the tuple. minLength: 1 type: string value: description: Value of the tuple. type: string required: - key - value type: object type: array hello: description: The hostname to identify to the SMTP server. type: string html: description: The HTML body of the email notification. type: string requireTLS: description: |- The SMTP TLS requirement. Note that Go does not support unencrypted connections to remote SMTP endpoints. type: boolean sendResolved: description: Whether or not to notify about resolved alerts. type: boolean smarthost: description: The SMTP host and port through which emails are sent. E.g. example.com:25 type: string text: description: The text body of the email notification. type: string tlsConfig: description: TLS configuration 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string 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 msteamsConfigs: description: |- List of MSTeams configurations. It requires Alertmanager >= 0.26.0. items: description: |- MSTeamsConfig configures notifications via Microsoft Teams. It requires Alertmanager >= 0.26.0. properties: httpConfig: description: HTTP client configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object sendResolved: description: Whether to notify about resolved alerts. type: boolean summary: description: |- Message summary template. It requires Alertmanager >= 0.27.0. type: string text: description: Message body template. type: string title: description: Message title template. type: string webhookUrl: description: MSTeams webhook URL. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic required: - webhookUrl type: object type: array msteamsv2Configs: description: |- List of MSTeamsV2 configurations. It requires Alertmanager >= 0.28.0. items: description: |- MSTeamsV2Config configures notifications via Microsoft Teams using the new message format with adaptive cards as required by flows See https://prometheus.io/docs/alerting/latest/configuration/#msteamsv2_config It requires Alertmanager >= 0.28.0. properties: httpConfig: description: HTTP client configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object sendResolved: description: Whether to notify about resolved alerts. type: boolean text: description: Message body template. minLength: 1 type: string title: description: Message title template. minLength: 1 type: string webhookURL: description: MSTeams incoming webhook URL. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object type: array name: description: Name of the receiver. Must be unique across all items from the list. minLength: 1 type: string opsgenieConfigs: description: List of OpsGenie configurations. items: description: |- OpsGenieConfig configures notifications via OpsGenie. See https://prometheus.io/docs/alerting/latest/configuration/#opsgenie_config properties: actions: description: Comma separated list of actions that will be available for the alert. type: string apiKey: description: |- The secret's key that contains the OpsGenie 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic apiURL: description: The URL to send OpsGenie API requests to. type: string description: description: Description of the incident. type: string details: description: A set of arbitrary key/value pairs that provide further detail about the incident. items: description: KeyValue defines a (key, value) tuple. properties: key: description: Key of the tuple. minLength: 1 type: string value: description: Value of the tuple. type: string required: - key - value type: object type: array entity: description: Optional field that can be used to specify which domain alert is related to. type: string httpConfig: description: HTTP client configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object 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 sendResolved: description: Whether or not to 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 updateAlerts: description: |- Whether to update message and description of the alert in OpsGenie if it already exists By default, the alert is never updated in OpsGenie, the new message only appears in activity log. type: boolean type: object type: array pagerdutyConfigs: description: List of PagerDuty 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 clientURL: 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: description: Arbitrary key/value pairs that provide further detail about the incident. items: description: KeyValue defines a (key, value) tuple. properties: key: description: Key of the tuple. minLength: 1 type: string value: description: Value of the tuple. type: string required: - key - value type: object type: array group: description: A cluster or grouping of sources. type: string httpConfig: description: HTTP client configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object pagerDutyImageConfigs: description: A list of image details to attach that provide further detail about an incident. items: description: PagerDutyImageConfig attaches images to an incident properties: alt: description: Alt is the optional alternative text for the image. type: string href: description: Optional URL; makes the image a clickable link. type: string src: description: Src of the image being attached to the incident type: string type: object type: array pagerDutyLinkConfigs: description: A list of link details to attach that provide further detail about an incident. items: description: PagerDutyLinkConfig attaches text links to an incident properties: alt: description: Text that describes the purpose of the link, and can be used as the link's text. type: string href: description: Href is the URL of the link to be attached type: string type: object type: array routingKey: 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. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic sendResolved: description: Whether or not to notify about resolved alerts. type: boolean serviceKey: 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. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic severity: description: Severity of the incident. type: string source: description: Unique location of the affected system. type: string url: description: The URL to send requests to. type: string type: object type: array pushoverConfigs: description: List of Pushover configurations. items: description: |- PushoverConfig configures notifications via Pushover. See https://prometheus.io/docs/alerting/latest/configuration/#pushover_config properties: device: description: The name of a device to send the notification to type: string expire: description: |- How long your notification will continue to be retried for, unless the user acknowledges the notification. pattern: ^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$ type: string html: description: Whether notification message is HTML or plain text. type: boolean httpConfig: description: HTTP client configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object 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. pattern: ^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$ type: string sendResolved: description: Whether or not to 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. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. Either `token` or `tokenFile` is required. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic tokenFile: description: |- The token file that contains the registered application's API token, see https://pushover.net/apps. Either `token` or `tokenFile` is required. It requires Alertmanager >= v0.26.0. type: string ttl: description: The time to live definition for the alert notification 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 url: description: A supplementary URL shown alongside the message. type: string urlTitle: description: A title for supplementary URL, otherwise just the URL is shown type: string userKey: description: |- The secret's key that contains the recipient user's user key. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. Either `userKey` or `userKeyFile` is required. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic userKeyFile: description: |- The user key file that contains the recipient user's user key. Either `userKey` or `userKeyFile` is required. It requires Alertmanager >= v0.26.0. type: string type: object type: array rocketchatConfigs: description: |- List of RocketChat configurations. It requires Alertmanager >= 0.28.0. items: description: |- RocketChatConfig configures notifications via RocketChat. It requires Alertmanager >= 0.28.0. properties: actions: description: Actions to include in the message. items: description: RocketChatActionConfig defines actions for RocketChat messages. properties: msg: description: The message to send when the button is clicked. minLength: 1 type: string text: description: The button text. minLength: 1 type: string url: description: The URL the button links to. pattern: ^https?://.+$ type: string type: object minItems: 1 type: array apiURL: description: |- The API URL for RocketChat. Defaults to https://open.rocket.chat/ if not specified. pattern: ^https?://.+$ type: string channel: description: The channel to send alerts to. minLength: 1 type: string color: description: The message color. minLength: 1 type: string emoji: description: If provided, the avatar will be displayed as an emoji. minLength: 1 type: string fields: description: Additional fields for the message. items: description: RocketChatFieldConfig defines additional fields for RocketChat messages. properties: short: description: Whether this field should be a short field. type: boolean title: description: The title of this field. minLength: 1 type: string value: description: The value of this field, displayed underneath the title value. minLength: 1 type: string type: object minItems: 1 type: array httpConfig: description: HTTP client configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object iconURL: description: Icon URL for the message. pattern: ^https?://.+$ type: string imageURL: description: Image URL for the message. pattern: ^https?://.+$ type: string linkNames: description: Whether to enable link names. type: boolean sendResolved: description: Whether to notify about resolved alerts. type: boolean shortFields: description: Whether to use short fields. type: boolean text: description: The message text to send, it is optional because of attachments. minLength: 1 type: string thumbURL: description: Thumbnail URL for the message. pattern: ^https?://.+$ type: string title: description: The message title. minLength: 1 type: string titleLink: description: The title link for the message. minLength: 1 type: string token: description: The sender token. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic tokenID: description: The sender token ID. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic required: - token - tokenID type: object type: array slackConfigs: description: List of Slack 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: dismissText: type: string okText: 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 apiURL: description: |- The secret's key that contains the Slack webhook URL. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic callbackId: 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. Each field must contain a title, value, and optionally, a boolean value to indicate if the field is short enough to be displayed next to other fields designated as short. 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 httpConfig: description: HTTP client configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object iconEmoji: type: string iconURL: type: string imageURL: type: string linkNames: type: boolean mrkdwnIn: items: type: string type: array pretext: type: string sendResolved: description: Whether or not to notify about resolved alerts. type: boolean shortFields: type: boolean text: type: string thumbURL: type: string title: type: string titleLink: type: string username: type: string type: object type: array snsConfigs: description: List of SNS configurations items: description: |- SNSConfig configures notifications via AWS SNS. See https://prometheus.io/docs/alerting/latest/configuration/#sns_configs properties: apiURL: description: |- The SNS API URL i.e. https://sns.us-east-2.amazonaws.com. If not specified, the SNS API URL from the SNS SDK will be used. type: string attributes: additionalProperties: type: string description: SNS message attributes. type: object httpConfig: description: HTTP client configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object message: description: The message content of the SNS notification. type: string phoneNumber: description: |- Phone number if message is delivered via SMS in E.164 format. If you don't specify this value, you must specify a value for the TopicARN or TargetARN. type: string sendResolved: description: Whether or not to notify about resolved alerts. type: boolean sigv4: description: Configures AWS's Signature Verification 4 signing process to sign requests. properties: accessKey: description: |- AccessKey is the AWS API key. If not specified, the environment variable `AWS_ACCESS_KEY_ID` is used. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic profile: description: Profile is the named AWS profile used to authenticate. type: string region: description: Region is the AWS region. If blank, the region from the default credentials chain used. type: string roleArn: description: RoleArn is the named AWS profile used to authenticate. type: string secretKey: description: |- SecretKey is the AWS API secret. If not specified, the environment variable `AWS_SECRET_ACCESS_KEY` is used. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object subject: description: Subject line when the message is delivered to email endpoints. type: string targetARN: description: |- The mobile platform endpoint ARN if message is delivered via mobile notifications. If you don't specify this value, you must specify a value for the topic_arn or PhoneNumber. type: string topicARN: description: |- SNS topic ARN, i.e. arn:aws:sns:us-east-2:698519295917:My-Topic If you don't specify this value, you must specify a value for the PhoneNumber or TargetARN. type: string type: object type: array telegramConfigs: description: List of Telegram configurations. items: description: |- TelegramConfig configures notifications via Telegram. See https://prometheus.io/docs/alerting/latest/configuration/#telegram_config properties: apiURL: description: |- The Telegram API URL i.e. https://api.telegram.org. If not specified, default API URL will be used. type: string botToken: description: |- Telegram bot token. It is mutually exclusive with `botTokenFile`. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. Either `botToken` or `botTokenFile` is required. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic botTokenFile: description: |- File to read the Telegram bot token from. It is mutually exclusive with `botToken`. Either `botToken` or `botTokenFile` is required. It requires Alertmanager >= v0.26.0. type: string chatID: description: The Telegram chat ID. format: int64 type: integer disableNotifications: description: Disable telegram notifications type: boolean httpConfig: description: HTTP client configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object message: description: Message template type: string messageThreadID: description: |- The Telegram Group Topic ID. It requires Alertmanager >= 0.26.0. format: int64 type: integer parseMode: description: Parse mode for telegram message enum: - MarkdownV2 - Markdown - HTML type: string sendResolved: description: Whether to notify about resolved alerts. type: boolean required: - chatID type: object type: array victoropsConfigs: description: List of VictorOps configurations. items: description: |- VictorOpsConfig configures notifications via VictorOps. See https://prometheus.io/docs/alerting/latest/configuration/#victorops_config properties: apiKey: description: |- The secret's key that contains the API key to use when talking to the VictorOps API. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic apiUrl: description: The VictorOps API URL. type: string customFields: description: Additional custom fields for notification. items: description: KeyValue defines a (key, value) tuple. properties: key: description: Key of the tuple. minLength: 1 type: string value: description: Value of the tuple. type: string required: - key - value type: object type: array entityDisplayName: description: Contains summary of the alerted problem. type: string httpConfig: description: The HTTP client's configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object messageType: description: Describes the behavior of the alert (CRITICAL, WARNING, INFO). type: string monitoringTool: description: The monitoring tool the state message is from. type: string routingKey: description: A key used to map the alert to a team. type: string sendResolved: description: Whether or not to notify about resolved alerts. type: boolean stateMessage: description: Contains long explanation of the alerted problem. type: string type: object type: array webexConfigs: description: List of Webex configurations. items: description: |- WebexConfig configures notification via Cisco Webex See https://prometheus.io/docs/alerting/latest/configuration/#webex_config properties: apiURL: description: |- The Webex Teams API URL i.e. https://webexapis.com/v1/messages Provide if different from the default API URL. pattern: ^https?://.+$ type: string httpConfig: description: |- The HTTP client's configuration. You must supply the bot token via the `httpConfig.authorization` field. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object message: description: Message template type: string roomID: description: ID of the Webex Teams room where to send the messages. minLength: 1 type: string sendResolved: description: Whether to notify about resolved alerts. type: boolean required: - roomID type: object type: array webhookConfigs: description: List of webhook 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: httpConfig: description: HTTP client configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object maxAlerts: description: Maximum number of alerts to be sent per webhook message. When 0, all alerts are included. format: int32 minimum: 0 type: integer sendResolved: description: Whether or not to notify about resolved alerts. type: boolean timeout: description: |- The maximum time to wait for a webhook request to complete, before failing the request and allowing it to be retried. It requires Alertmanager >= v0.28.0. 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 url: description: |- The URL to send HTTP POST requests to. `urlSecret` takes precedence over `url`. One of `urlSecret` and `url` should be defined. type: string urlSecret: description: |- The secret's key that contains the webhook URL to send HTTP requests to. `urlSecret` takes precedence over `url`. One of `urlSecret` and `url` should be defined. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object type: array wechatConfigs: description: List of WeChat configurations. items: description: |- WeChatConfig configures notifications via WeChat. See https://prometheus.io/docs/alerting/latest/configuration/#wechat_config properties: agentID: type: string apiSecret: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic apiURL: description: The WeChat API URL. type: string corpID: description: The corp id for authentication. type: string httpConfig: description: HTTP client configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyURL: description: |- Optional proxy URL. If defined, this field takes precedence over `proxyUrl`. type: string proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string 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 messageType: type: string sendResolved: description: Whether or not to notify about resolved alerts. type: boolean toParty: type: string toTag: type: string toUser: type: string type: object type: array required: - name type: object type: array route: description: |- The Alertmanager route definition for alerts matching the resource's namespace. If present, it will be added to the generated Alertmanager configuration as a first-level route. properties: activeTimeIntervals: description: ActiveTimeIntervals is a list of MuteTimeInterval names when this route should be active. items: type: string type: array continue: description: |- Boolean indicating whether an alert should continue matching subsequent sibling nodes. It will always be overridden to true for the first-level route by the Prometheus operator. type: boolean groupBy: description: |- List of labels to group by. Labels must not be repeated (unique list). Special label "..." (aggregate by all possible labels), if provided, must be the only element in the list. items: type: string type: array groupInterval: description: |- How long to wait before sending an updated notification. Must match the regular expression`^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$` Example: "5m" type: string groupWait: description: |- How long to wait before sending the initial notification. Must match the regular expression`^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$` Example: "30s" type: string matchers: description: |- List of matchers that the alert's labels should match. For the first level route, the operator removes any existing equality and regexp matcher on the `namespace` label and adds a `namespace: ` matcher. items: description: Matcher defines how to match on alert's labels. properties: matchType: description: |- Match operation available with AlertManager >= v0.22.0 and takes precedence over Regex (deprecated) if non-empty. enum: - '!=' - = - =~ - '!~' type: string name: description: Label to match. minLength: 1 type: string regex: description: |- Whether to match on equality (false) or regular-expression (true). Deprecated: for AlertManager >= v0.22.0, `matchType` should be used instead. type: boolean value: description: Label value to match. type: string required: - name type: object type: array muteTimeIntervals: description: |- Note: this comment applies to the field definition above but appears below otherwise it gets included in the generated manifest. CRD schema doesn't support self-referential types for now (see https://github.com/kubernetes/kubernetes/issues/62872). We have to use an alternative type to circumvent the limitation. The downside is that the Kube API can't validate the data beyond the fact that it is a valid JSON representation. MuteTimeIntervals is a list of MuteTimeInterval names that will mute this route when matched, items: type: string type: array receiver: description: |- Name of the receiver for this route. If not empty, it should be listed in the `receivers` field. type: string repeatInterval: description: |- How long to wait before repeating the last notification. Must match the regular expression`^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$` Example: "4h" type: string routes: description: Child routes. items: x-kubernetes-preserve-unknown-fields: true type: array type: object type: object required: - spec type: object served: true storage: true ================================================ FILE: hack/config/monitoring/crds/0alertmanagerCustomResourceDefinition.yaml ================================================ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 operator.prometheus.io/version: 0.85.0 name: alertmanagers.monitoring.coreos.com spec: group: monitoring.coreos.com names: categories: - prometheus-operator kind: Alertmanager listKind: AlertmanagerList plural: alertmanagers shortNames: - am singular: alertmanager scope: Namespaced versions: - additionalPrinterColumns: - description: The version of Alertmanager jsonPath: .spec.version name: Version type: string - description: The number of desired replicas jsonPath: .spec.replicas name: Replicas type: integer - description: The number of ready replicas jsonPath: .status.availableReplicas name: Ready type: integer - jsonPath: .status.conditions[?(@.type == 'Reconciled')].status name: Reconciled type: string - jsonPath: .status.conditions[?(@.type == 'Available')].status name: Available type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - description: Whether the resource reconciliation is paused or not jsonPath: .status.paused name: Paused priority: 1 type: boolean name: v1 schema: openAPIV3Schema: description: |- The `Alertmanager` custom resource definition (CRD) defines a desired [Alertmanager](https://prometheus.io/docs/alerting) setup to run in a Kubernetes cluster. It allows to specify many options such as the number of replicas, persistent storage and many more. For each `Alertmanager` resource, the Operator deploys a `StatefulSet` in the same namespace. When there are two or more configured replicas, the Operator runs the Alertmanager instances in high-availability mode. The resource defines via label and namespace selectors which `AlertmanagerConfig` objects should be associated to the deployed Alertmanager instances. 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 Alertmanager cluster. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status properties: additionalArgs: description: |- AdditionalArgs allows setting additional arguments for the 'Alertmanager' container. It is intended for e.g. activating hidden flags which are not supported by the dedicated configuration options yet. The arguments are passed as-is to the Alertmanager container which may cause issues if they are invalid or not supported by the given Alertmanager version. items: description: Argument as part of the AdditionalArgs list. properties: name: description: Name of the argument, e.g. "scrape.discovery-reload-interval". minLength: 1 type: string value: description: Argument value, e.g. 30s. Can be empty for name-only arguments (e.g. --storage.tsdb.no-lockfile) type: string required: - name type: object type: array 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: 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic type: object type: object alertmanagerConfigMatcherStrategy: description: |- AlertmanagerConfigMatcherStrategy defines how AlertmanagerConfig objects process incoming alerts. properties: type: default: OnNamespace description: |- AlertmanagerConfigMatcherStrategyType defines the strategy used by AlertmanagerConfig objects to match alerts in the routes and inhibition rules. The default value is `OnNamespace`. enum: - OnNamespace - OnNamespaceExceptForAlertmanagerNamespace - None type: string type: object alertmanagerConfigNamespaceSelector: description: |- Namespaces to be selected for AlertmanagerConfig discovery. If nil, only check own 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic alertmanagerConfigSelector: description: AlertmanagerConfigs to be selected for to merge and configure Alertmanager with. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic alertmanagerConfiguration: description: |- alertmanagerConfiguration specifies the configuration of Alertmanager. If defined, it takes precedence over the `configSecret` field. This is an *experimental feature*, it may change in any upcoming release in a breaking way. properties: global: description: Defines the global parameters of the Alertmanager configuration. properties: httpConfig: description: HTTP client configuration. properties: authorization: description: |- Authorization header configuration for the client. This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth for the client. This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- The secret's key that contains the bearer token to be used by the client for authentication. The secret needs to be in the same namespace as the Alertmanager 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic followRedirects: description: FollowRedirects specifies whether the client should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: OAuth2 client credentials used to fetch a token for the targets. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS configuration for the client. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object jira: description: The default configuration for Jira. properties: apiURL: description: |- The default Jira API URL. It requires Alertmanager >= v0.28.0. pattern: ^(http|https)://.+$ type: string type: object opsGenieApiKey: description: The default OpsGenie API Key. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic opsGenieApiUrl: description: The default OpsGenie API URL. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic pagerdutyUrl: description: The default Pagerduty URL. type: string resolveTimeout: description: |- ResolveTimeout is the default value used by alertmanager if the alert does not include EndsAt, after this time passes it can declare the alert as resolved if it has not been updated. This has no impact on alerts from Prometheus, as they always include EndsAt. 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 rocketChat: description: The default configuration for Rocket Chat. properties: apiURL: description: |- The default Rocket Chat API URL. It requires Alertmanager >= v0.28.0. pattern: ^(http|https)://.+$ type: string token: description: |- The default Rocket Chat token. It requires Alertmanager >= v0.28.0. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic tokenID: description: |- The default Rocket Chat Token ID. It requires Alertmanager >= v0.28.0. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object slackApiUrl: description: The default Slack API URL. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic smtp: description: Configures global SMTP parameters. properties: authIdentity: description: SMTP Auth using PLAIN type: string authPassword: description: SMTP Auth using LOGIN and PLAIN. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic authSecret: description: SMTP Auth using CRAM-MD5. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic authUsername: description: SMTP Auth using CRAM-MD5, LOGIN and PLAIN. If empty, Alertmanager doesn't authenticate to the SMTP server. type: string from: description: The default SMTP From header field. type: string hello: description: The default hostname to identify to the SMTP server. type: string requireTLS: description: |- The default SMTP TLS requirement. Note that Go does not support unencrypted connections to remote SMTP endpoints. type: boolean smartHost: description: The default SMTP smarthost used for sending emails. properties: host: description: Defines the host's address, it can be a DNS name or a literal IP address. minLength: 1 type: string port: description: Defines the host's port, it can be a literal port number or a port name. minLength: 1 type: string required: - host - port type: object tlsConfig: description: The default TLS configuration for SMTP receivers 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object telegram: description: The default Telegram config properties: apiURL: description: |- The default Telegram API URL. It requires Alertmanager >= v0.24.0. pattern: ^(http|https)://.+$ type: string type: object victorops: description: The default configuration for VictorOps. properties: apiKey: description: The default VictorOps API Key. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic apiURL: description: The default VictorOps API URL. pattern: ^(http|https)://.+$ type: string type: object webex: description: The default configuration for Jira. properties: apiURL: description: |- The default Webex API URL. It requires Alertmanager >= v0.25.0. pattern: ^(http|https)://.+$ type: string type: object wechat: description: The default WeChat Config properties: apiCorpID: description: The default WeChat API Corporate ID. minLength: 1 type: string apiSecret: description: The default WeChat API Secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic apiURL: description: |- The default WeChat API URL. The default value is "https://qyapi.weixin.qq.com/cgi-bin/" pattern: ^(http|https)://.+$ type: string type: object type: object name: description: |- The name of the AlertmanagerConfig resource which is used to generate the Alertmanager configuration. It must be defined in the same namespace as the Alertmanager object. The operator will not enforce a `namespace` label for routes and inhibition rules. minLength: 1 type: string templates: description: Custom notification templates. items: description: SecretOrConfigMap allows to specify data as a Secret or ConfigMap. Fields are mutually exclusive. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object type: array type: object automountServiceAccountToken: description: |- AutomountServiceAccountToken indicates whether a service account token should be automatically mounted in the pod. If the service account has `automountServiceAccountToken: true`, set the field to `false` to opt out of automounting API credentials. type: boolean baseImage: description: |- Base image that is used to deploy pods, without tag. Deprecated: use 'image' instead. type: string 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 clusterGossipInterval: description: Interval between gossip attempts. pattern: ^(0|(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ type: string clusterLabel: description: |- Defines the identifier that uniquely identifies the Alertmanager cluster. You should only set it when the Alertmanager cluster includes Alertmanager instances which are external to this Alertmanager resource. In practice, the addresses of the external instances are provided via the `.spec.additionalPeers` field. type: string clusterPeerTimeout: description: Timeout for cluster peering. pattern: ^(0|(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ type: string clusterPushpullInterval: description: Interval between pushpull attempts. pattern: ^(0|(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ type: string clusterTLS: description: |- Configures the mutual TLS configuration for the Alertmanager cluster's gossip protocol. It requires Alertmanager >= 0.24.0. properties: client: description: Client-side configuration for mutual TLS. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object server: description: Server-side configuration for mutual TLS. properties: cert: description: |- Secret or ConfigMap containing the TLS certificate for the web server. Either `keySecret` or `keyFile` must be defined. It is mutually exclusive with `certFile`. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object certFile: description: |- Path to the TLS certificate file in the container for the web server. Either `keySecret` or `keyFile` must be defined. It is mutually exclusive with `cert`. type: string cipherSuites: description: |- List of supported cipher suites for TLS versions up to TLS 1.2. If not defined, the Go default cipher suites are used. Available cipher suites are documented in the Go documentation: https://golang.org/pkg/crypto/tls/#pkg-constants items: type: string type: array client_ca: description: |- Secret or ConfigMap containing the CA certificate for client certificate authentication to the server. It is mutually exclusive with `clientCAFile`. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientAuthType: description: |- The server policy for client TLS authentication. For more detail on clientAuth options: https://golang.org/pkg/crypto/tls/#ClientAuthType type: string clientCAFile: description: |- Path to the CA certificate file for client certificate authentication to the server. It is mutually exclusive with `client_ca`. type: string curvePreferences: description: |- Elliptic curves that will be used in an ECDHE handshake, in preference order. Available curves are documented in the Go documentation: https://golang.org/pkg/crypto/tls/#CurveID items: type: string type: array keyFile: description: |- Path to the TLS private key file in the container for the web server. If defined, either `cert` or `certFile` must be defined. It is mutually exclusive with `keySecret`. type: string keySecret: description: |- Secret containing the TLS private key for the web server. Either `cert` or `certFile` must be defined. It is mutually exclusive with `keyFile`. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: Maximum TLS version that is acceptable. type: string minVersion: description: Minimum TLS version that is acceptable. type: string preferServerCipherSuites: description: |- Controls whether the server selects the client's most preferred cipher suite, or the server's most preferred cipher suite. If true then the server's preference, as expressed in the order of elements in cipherSuites, is used. type: boolean type: object required: - client - server type: object configMaps: description: |- ConfigMaps is a list of ConfigMaps in the same namespace as the Alertmanager object, which shall be mounted into the Alertmanager Pods. Each ConfigMap is added to the StatefulSet definition as a volume named `configmap-`. The ConfigMaps are mounted into `/etc/alertmanager/configmaps/` in the 'alertmanager' container. items: type: string type: array configSecret: description: |- ConfigSecret is the name of a Kubernetes Secret in the same namespace as the Alertmanager object, which contains the configuration for this Alertmanager instance. If empty, it defaults to `alertmanager-`. The Alertmanager configuration should be available under the `alertmanager.yaml` key. Additional keys from the original secret are copied to the generated secret and mounted into the `/etc/alertmanager/config` directory in the `alertmanager` container. If either the secret or the `alertmanager.yaml` key is missing, the operator provisions a minimal Alertmanager configuration with one empty receiver (effectively dropping alert notifications). type: string containers: description: |- Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to an Alertmanager pod. Containers described here modify an operator generated container if they share the same name and modifications are done via a strategic merge patch. The current container names are: `alertmanager` and `config-reloader`. Overriding containers 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. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: description: |- Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string description: Specifies the output format of the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: description: Selects a key of a secret in the pod's namespace properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map 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 or Secrets properties: configMapRef: description: The ConfigMap to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret must be defined type: boolean type: object x-kubernetes-map-type: atomic type: object type: array x-kubernetes-list-type: atomic 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 stopSignal: description: |- StopSignal defines which signal will be sent to a container when it is being stopped. If not specified, the default is defined by the container runtime in use. StopSignal can only be set for Pods with a non-empty .spec.os.name type: string 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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. This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: description: |- Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. type: string request: description: |- Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object 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 appArmorProfile: description: |- appArmorProfile is the AppArmor options to use by this container. If set, this profile overrides the pod's appArmorProfile. Note that this field cannot be set when spec.os.name is windows. properties: localhostProfile: description: |- localhostProfile indicates a profile loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost". type: string type: description: |- type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement. type: string required: - type type: object 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 x-kubernetes-list-type: atomic drop: description: Removed capabilities items: description: Capability represent POSIX capabilities type type: string type: array x-kubernetes-list-type: atomic 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 value is Default 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: 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 x-kubernetes-list-map-keys: - devicePath x-kubernetes-list-type: map 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. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None). 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 recursiveReadOnly: description: |- RecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled. type: string 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 x-kubernetes-list-map-keys: - mountPath x-kubernetes-list-type: map 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: Defines the DNS configuration for the pods. properties: nameservers: description: |- A list of DNS name server IP addresses. This will be appended to the base nameservers generated from DNSPolicy. items: minLength: 1 type: string type: array x-kubernetes-list-type: set options: description: |- A list of DNS resolver options. This will be merged with the base options generated from DNSPolicy. 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: Name is required and must be unique. minLength: 1 type: string value: description: Value is optional. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map searches: description: |- A list of DNS search domains for host-name lookup. This will be appended to the base search paths generated from DNSPolicy. items: minLength: 1 type: string type: array x-kubernetes-list-type: set type: object dnsPolicy: description: Defines the DNS policy for the pods. enum: - ClusterFirstWithHostNet - ClusterFirst - Default - None type: string enableFeatures: description: |- Enable access to Alertmanager feature flags. By default, no features are enabled. Enabling features which are disabled by default 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. It requires Alertmanager >= 0.27.0. items: type: string type: array enableServiceLinks: description: Indicates whether information about services should be injected into pod's environment variables type: boolean externalUrl: description: |- The external URL the Alertmanager instances will be available under. This is necessary to generate correct URLs. This is necessary if Alertmanager is not served from root of a DNS name. type: string forceEnableClusterMode: description: |- ForceEnableClusterMode ensures Alertmanager does not deactivate the cluster mode when running with a single replica. Use case is e.g. spanning an Alertmanager cluster across Kubernetes clusters with a single replica in each. type: boolean hostAliases: description: Pods' hostAliases configuration 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 required: - hostnames - ip type: object type: array x-kubernetes-list-map-keys: - ip x-kubernetes-list-type: map hostUsers: description: |- HostUsers supports the user space in Kubernetes. More info: https://kubernetes.io/docs/tasks/configure-pod-container/user-namespaces/ The feature requires at least Kubernetes 1.28 with the `UserNamespacesSupport` feature gate enabled. Starting Kubernetes 1.33, the feature is enabled by default. type: boolean image: description: |- Image if specified has precedence over baseImage, tag and sha combinations. Specifying the version is still necessary to ensure the Prometheus Operator knows what version of Alertmanager is being configured. type: string imagePullPolicy: description: |- Image pull policy for the 'alertmanager', 'init-config-reloader' and 'config-reloader' containers. See https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy for more details. enum: - "" - Always - Never - IfNotPresent type: string imagePullSecrets: description: |- An optional list of references to secrets in the same namespace to use for pulling prometheus and alertmanager images from registries see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ items: description: |- LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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 Alertmanager 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/ InitContainers described here modify an operator generated init containers if they share the same name and modifications are done via a strategic merge patch. The current init container name is: `init-config-reloader`. Overriding init containers 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. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: description: |- Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string description: Specifies the output format of the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: description: Selects a key of a secret in the pod's namespace properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map 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 or Secrets properties: configMapRef: description: The ConfigMap to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret must be defined type: boolean type: object x-kubernetes-map-type: atomic type: object type: array x-kubernetes-list-type: atomic 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 stopSignal: description: |- StopSignal defines which signal will be sent to a container when it is being stopped. If not specified, the default is defined by the container runtime in use. StopSignal can only be set for Pods with a non-empty .spec.os.name type: string 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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. This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: description: |- Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. type: string request: description: |- Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object 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 appArmorProfile: description: |- appArmorProfile is the AppArmor options to use by this container. If set, this profile overrides the pod's appArmorProfile. Note that this field cannot be set when spec.os.name is windows. properties: localhostProfile: description: |- localhostProfile indicates a profile loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost". type: string type: description: |- type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement. type: string required: - type type: object 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 x-kubernetes-list-type: atomic drop: description: Removed capabilities items: description: Capability represent POSIX capabilities type type: string type: array x-kubernetes-list-type: atomic 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 value is Default 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: 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 x-kubernetes-list-map-keys: - devicePath x-kubernetes-list-type: map 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. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None). 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 recursiveReadOnly: description: |- RecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled. type: string 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 x-kubernetes-list-map-keys: - mountPath x-kubernetes-list-type: map 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 limits: description: Defines the limits command line flags when starting Alertmanager. properties: maxPerSilenceBytes: description: |- The maximum size of an individual silence as stored on disk. This corresponds to the Alertmanager's `--silences.max-per-silence-bytes` flag. It requires Alertmanager >= v0.28.0. pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$ type: string maxSilences: description: |- The maximum number active and pending silences. This corresponds to the Alertmanager's `--silences.max-silences` flag. It requires Alertmanager >= v0.28.0. format: int32 minimum: 0 type: integer type: object listenLocal: description: |- ListenLocal makes the Alertmanager server listen on loopback, so that it does not bind against the Pod IP. Note this is only for the Alertmanager UI, not the gossip communication. type: boolean logFormat: description: Log format for Alertmanager to be configured with. enum: - "" - logfmt - json type: string logLevel: description: Log level for Alertmanager to be configured with. enum: - "" - debug - info - warn - error type: string minReadySeconds: description: |- Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to be considered available. If unset, pods will be considered available as soon as they are ready. format: int32 minimum: 0 type: integer nodeSelector: additionalProperties: type: string description: Define which Nodes the Pods are scheduled on. type: object paused: description: |- If set to true all actions on the underlying managed objects are not going to be performed, except for delete actions. type: boolean persistentVolumeClaimRetentionPolicy: description: |- The field controls if and how PVCs are deleted during the lifecycle of a StatefulSet. The default behavior is all PVCs are retained. This is an alpha field from kubernetes 1.23 until 1.26 and a beta field from 1.26. It requires enabling the StatefulSetAutoDeletePVC feature gate. properties: whenDeleted: description: |- WhenDeleted specifies what happens to PVCs created from StatefulSet VolumeClaimTemplates when the StatefulSet is deleted. The default policy of `Retain` causes PVCs to not be affected by StatefulSet deletion. The `Delete` policy causes those PVCs to be deleted. type: string whenScaled: description: |- WhenScaled specifies what happens to PVCs created from StatefulSet VolumeClaimTemplates when the StatefulSet is scaled down. The default policy of `Retain` causes PVCs to not be affected by a scaledown. The `Delete` policy causes the associated PVCs for any excess pods above the replica count to be deleted. type: string type: object podMetadata: description: |- PodMetadata configures labels and annotations which are propagated to the Alertmanager pods. The following items are reserved and cannot be overridden: * "alertmanager" label, set to the name of the Alertmanager instance. * "app.kubernetes.io/instance" label, set to the name of the Alertmanager instance. * "app.kubernetes.io/managed-by" label, set to "prometheus-operator". * "app.kubernetes.io/name" label, set to "alertmanager". * "app.kubernetes.io/version" label, set to the Alertmanager version. * "kubectl.kubernetes.io/default-container" annotation, set to "alertmanager". 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. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/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: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/ type: string type: object portName: default: web description: |- Port name used for the pods and governing service. Defaults to `web`. type: string priorityClassName: description: Priority class assigned to the Pods type: string replicas: description: |- Size is the expected size of the alertmanager cluster. The controller will eventually make the size of the running cluster equal to the expected size. format: int32 type: integer resources: description: Define resources requests and limits for single Pods. properties: claims: description: |- Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: description: |- Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. type: string request: description: |- Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object retention: default: 120h description: |- Time duration Alertmanager 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|(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ type: string routePrefix: description: |- The route prefix Alertmanager 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 secrets: description: |- Secrets is a list of Secrets in the same namespace as the Alertmanager object, which shall be mounted into the Alertmanager Pods. Each Secret is added to the StatefulSet definition as a volume named `secret-`. The Secrets are mounted into `/etc/alertmanager/secrets/` in the 'alertmanager' container. items: type: string type: array securityContext: description: |- SecurityContext holds pod-level security attributes and common container settings. This defaults to the default PodSecurityContext. properties: appArmorProfile: description: |- appArmorProfile is the AppArmor 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 loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost". type: string type: description: |- type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement. type: string required: - type type: object 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: 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---- 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 seLinuxChangePolicy: description: |- seLinuxChangePolicy defines how the container's SELinux label is applied to all volumes used by the Pod. It has no effect on nodes that do not support SELinux or to volumes does not support SELinux. Valid values are "MountOption" and "Recursive". "Recursive" means relabeling of all files on all Pod volumes by the container runtime. This may be slow for large volumes, but allows mixing privileged and unprivileged Pods sharing the same volume on the same node. "MountOption" mounts all eligible Pod volumes with `-o context` mount option. This requires all Pods that share the same volume to use the same SELinux label. It is not possible to share the same volume among privileged and unprivileged Pods. Eligible volumes are in-tree FibreChannel and iSCSI volumes, and all CSI volumes whose CSI driver announces SELinux support by setting spec.seLinuxMount: true in their CSIDriver instance. Other volumes are always re-labelled recursively. "MountOption" value is allowed only when SELinuxMount feature gate is enabled. If not specified and SELinuxMount feature gate is enabled, "MountOption" is used. If not specified and SELinuxMount feature gate is disabled, "MountOption" is used for ReadWriteOncePod volumes and "Recursive" for all other volumes. This field affects only Pods that have SELinux label set, either in PodSecurityContext or in SecurityContext of all containers. All Pods that use the same volume should use the same seLinuxChangePolicy, otherwise some pods can get stuck in ContainerCreating state. Note that this field cannot be set when spec.os.name is windows. type: string 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: 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 and fsGroup (if specified). If the SupplementalGroupsPolicy feature is enabled, the supplementalGroupsPolicy field determines whether these are in addition to or instead of any group memberships defined in the container image. If unspecified, no additional groups are added, though group memberships defined in the container image may still be used, depending on the supplementalGroupsPolicy field. Note that this field cannot be set when spec.os.name is windows. items: format: int64 type: integer type: array x-kubernetes-list-type: atomic supplementalGroupsPolicy: description: |- Defines how supplemental groups of the first container processes are calculated. Valid values are "Merge" and "Strict". If not specified, "Merge" is used. (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled and the container runtime must implement support for this feature. Note that this field cannot be set when spec.os.name is windows. type: string 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 x-kubernetes-list-type: atomic 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 serviceAccountName: description: |- ServiceAccountName is the name of the ServiceAccount to use to run the Prometheus Pods. type: string serviceName: description: |- The name of the service name used by the underlying StatefulSet(s) as the governing service. If defined, the Service must be created before the Alertmanager resource in the same namespace and it must define a selector that matches the pod labels. If empty, the operator will create and manage a headless service named `alertmanager-operated` for Alermanager resources. When deploying multiple Alertmanager resources in the same namespace, it is recommended to specify a different value for each. See https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id for more details. minLength: 1 type: string sha: description: |- SHA of Alertmanager container image to be deployed. Defaults to the value of `version`. Similar to a tag, but the SHA explicitly deploys an immutable container image. Version and Tag are ignored if SHA is set. Deprecated: use 'image' instead. The image digest can be specified as part of the image URL. type: string storage: description: |- Storage is the definition of how storage will be used by the Alertmanager instances. properties: disableMountSubPath: description: 'Deprecated: subPath usage will be removed in a future release.' type: boolean emptyDir: description: |- EmptyDirVolumeSource to be used by the StatefulSet. If specified, it takes precedence over `ephemeral` and `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: 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: |- EphemeralVolumeSource to be used by the StatefulSet. This is a beta field in k8s 1.21 and GA in 1.15. For lower versions, starting with k8s 1.19, it requires enabling the GenericEphemeralVolume feature gate. More info: https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volumes 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). 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. This field is read-only and no changes will be made by Kubernetes to the PVC after it has been created. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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/volume-attributes-classes/ (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). 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 volumeClaimTemplate: description: |- Defines the PVC spec to be used by the Prometheus StatefulSets. The easiest way to use a volume that cannot be automatically provisioned is to use a label selector alongside manually created PersistentVolumes. 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: 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. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/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: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/ type: string type: object spec: description: |- 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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/volume-attributes-classes/ (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). 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: 'Deprecated: this field is never set.' 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 x-kubernetes-list-type: atomic allocatedResourceStatuses: additionalProperties: description: |- When a controller receives persistentvolume claim update with ClaimResourceStatus for a resource that it does not recognizes, then it should ignore that update and let other controllers handle it. type: string description: "allocatedResourceStatuses stores status of resource being resized for the given PVC.\nKey names follow standard Kubernetes label syntax. Valid values are either:\n\t* Un-prefixed keys:\n\t\t- storage - the capacity of the volume.\n\t* Custom resources must use implementation-defined prefixed names such as \"example.com/my-custom-resource\"\nApart from above values - keys that are unprefixed or have kubernetes.io prefix are considered\nreserved and hence may not be used.\n\nClaimResourceStatus can be in any of following states:\n\t- ControllerResizeInProgress:\n\t\tState set when resize controller starts resizing the volume in control-plane.\n\t- ControllerResizeFailed:\n\t\tState set when resize has failed in resize controller with a terminal error.\n\t- NodeResizePending:\n\t\tState set when resize controller has finished resizing the volume but further resizing of\n\t\tvolume is needed on the node.\n\t- NodeResizeInProgress:\n\t\tState set when kubelet starts resizing the volume.\n\t- NodeResizeFailed:\n\t\tState set when resizing has failed in kubelet with a terminal error. Transient errors don't set\n\t\tNodeResizeFailed.\nFor example: if expanding a PVC for more capacity - this field can be one of the following states:\n\t- pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeInProgress\"\n - pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeFailed\"\n - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizePending\"\n - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeInProgress\"\n - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeFailed\"\nWhen this field is not set, it means that no resize operation is in progress for the given PVC.\n\nA controller that receives PVC update with previously unknown resourceName or ClaimResourceStatus\nshould ignore the update for the purpose it was designed. For example - a controller that\nonly is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid\nresources associated with PVC.\n\nThis is an alpha field and requires enabling RecoverVolumeExpansionFailure feature." type: object x-kubernetes-map-type: granular 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 tracks the resources allocated to a PVC including its capacity.\nKey names follow standard Kubernetes label syntax. Valid values are either:\n\t* Un-prefixed keys:\n\t\t- storage - the capacity of the volume.\n\t* Custom resources must use implementation-defined prefixed names such as \"example.com/my-custom-resource\"\nApart from above values - keys that are unprefixed or have kubernetes.io prefix are considered\nreserved and hence may not be used.\n\nCapacity reported here may be larger than the actual capacity when a volume expansion operation\nis requested.\nFor storage quota, the larger value from allocatedResources and PVC.spec.resources is used.\nIf allocatedResources is not set, PVC.spec.resources alone is used for quota calculation.\nIf a volume expansion capacity request is lowered, allocatedResources is only\nlowered if there are no expansion operations in progress and if the actual volume capacity\nis equal or lower than the requested capacity.\n\nA controller that receives PVC update with previously unknown resourceName\nshould ignore the update for the purpose it was designed. For example - a controller that\nonly is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid\nresources associated with PVC.\n\nThis 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 'Resizing'. items: description: PersistentVolumeClaimCondition contains 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 "Resizing" that means the underlying persistent volume is being resized. type: string status: description: |- Status is the status of the condition. Can be True, False, Unknown. More info: https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/persistent-volume-claim-v1/#:~:text=state%20of%20pvc-,conditions.status,-(string)%2C%20required type: string type: description: |- Type is the type of the condition. More info: https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/persistent-volume-claim-v1/#:~:text=set%20to%20%27ResizeStarted%27.-,PersistentVolumeClaimCondition,-contains%20details%20about type: string required: - status - type type: object type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map currentVolumeAttributesClassName: description: |- currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using. When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim This is a beta field and requires enabling VolumeAttributesClass feature (off by default). type: string modifyVolumeStatus: description: |- ModifyVolumeStatus represents the status object of ControllerModifyVolume operation. When this is unset, there is no ModifyVolume operation being attempted. This is a beta field and requires enabling VolumeAttributesClass feature (off by default). properties: status: description: "status is the status of the ControllerModifyVolume operation. It can be in any of following states:\n - Pending\n Pending indicates that the PersistentVolumeClaim cannot be modified due to unmet requirements, such as\n the specified VolumeAttributesClass not existing.\n - InProgress\n InProgress indicates that the volume is being modified.\n - Infeasible\n Infeasible indicates that the request has been rejected as invalid by the CSI driver. To\n\t resolve the error, a valid VolumeAttributesClass needs to be specified.\nNote: New statuses can be added in the future. Consumers should check for unknown statuses and fail appropriately." type: string targetVolumeAttributesClassName: description: targetVolumeAttributesClassName is the name of the VolumeAttributesClass the PVC currently being reconciled type: string required: - status type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string type: object type: object type: object tag: description: |- Tag of Alertmanager container image to be deployed. Defaults to the value of `version`. Version is ignored if Tag is set. Deprecated: use 'image' instead. The image tag can be specified as part of the image URL. type: string terminationGracePeriodSeconds: description: |- Optional duration in seconds the pod needs to terminate gracefully. Value must be non-negative integer. The value zero indicates stop immediately via the kill signal (no opportunity to shut down) which may lead to data corruption. Defaults to 120 seconds. format: int64 minimum: 0 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: If specified, the pod's 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. MatchLabelKeys cannot be set when LabelSelector isn't set. Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. 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. 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. format: int32 type: integer nodeAffinityPolicy: description: |- NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. type: string nodeTaintsPolicy: description: |- NodeTaintsPolicy indicates how we will treat node taints when calculating pod topology spread skew. Options are: - Honor: nodes without taints, along with tainted nodes for which the incoming pod has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. 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 version: description: Version the cluster should be on. type: string 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. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None). 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 recursiveReadOnly: description: |- RecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled. type: string 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. properties: awsElasticBlockStore: description: |- awsElasticBlockStore represents an AWS Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Deprecated: AWSElasticBlockStore is deprecated. All operations for the in-tree awsElasticBlockStore type are redirected to the ebs.csi.aws.com CSI driver. 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 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. Deprecated: AzureDisk is deprecated. All operations for the in-tree azureDisk type are redirected to the disk.csi.azure.com CSI driver. 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: default: ext4 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: default: false 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. Deprecated: AzureFile is deprecated. All operations for the in-tree azureFile type are redirected to the file.csi.azure.com CSI driver. 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. Deprecated: CephFS is deprecated and the in-tree cephfs type is no longer supported. 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: Cinder is deprecated. All operations for the in-tree cinder type are redirected to the cinder.csi.openstack.org CSI driver. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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 x-kubernetes-list-type: atomic name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: 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. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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, namespace and uid 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 x-kubernetes-list-type: atomic 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. 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). Use PersistentVolumeClaim or one of the vendor-specific APIs for volumes that persist for longer than the lifecycle of an individual pod. 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. 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). 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. This field is read-only and no changes will be made by Kubernetes to the PVC after it has been created. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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/volume-attributes-classes/ (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). 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. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic type: object flexVolume: description: |- flexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. Deprecated: FlexVolume is deprecated. Consider using a CSIDriver instead. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: Flocker is deprecated and the in-tree flocker type is no longer supported. 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. Deprecated: GCEPersistentDisk is deprecated. All operations for the in-tree gcePersistentDisk type are redirected to the pd.csi.storage.gke.io CSI driver. 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 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. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported. 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 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 image: description: |- image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided: - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. The volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro) and non-executable files (noexec). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: pullPolicy: description: |- Policy for pulling OCI objects. Possible values are: Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. type: string reference: description: |- Required: Image or artifact reference to be used. Behaves in the same way as pod.spec.containers[*].image. Pull secrets will be assembled in the same way as for the container image by looking up node credentials, SA image pull secrets, and pod spec image pull secrets. 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 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 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: default: default 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: PhotonPersistentDisk is deprecated and the in-tree photonPersistentDisk type is no longer supported. 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. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on. 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. Each entry in this list handles one source. items: description: |- Projection that may be projected along with other supported volume types. Exactly one of these fields must be set. properties: clusterTrustBundle: description: |- ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. Alpha, gated by the ClusterTrustBundleProjection feature gate. ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: 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, namespace and uid 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: 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 x-kubernetes-list-type: atomic type: object quobyte: description: |- quobyte represents a Quobyte mount on the host that shares a pod's lifetime. Deprecated: Quobyte is deprecated and the in-tree quobyte type is no longer supported. 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. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. 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 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: default: /etc/ceph/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 x-kubernetes-list-type: atomic pool: default: rbd 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string type: object x-kubernetes-map-type: atomic user: default: admin 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. Deprecated: ScaleIO is deprecated and the in-tree scaleIO type is no longer supported. properties: fsType: default: xfs 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string type: object x-kubernetes-map-type: atomic sslEnabled: description: sslEnabled Flag enable/disable SSL communication with Gateway, default false type: boolean storageMode: default: ThinProvisioned 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 x-kubernetes-list-type: atomic 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. Deprecated: StorageOS is deprecated and the in-tree storageos type is no longer supported. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: VsphereVolume is deprecated. All operations for the in-tree vsphereVolume type are redirected to the csi.vsphere.vmware.com CSI driver. 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 web: description: Defines the web command line flags when starting Alertmanager. properties: getConcurrency: description: |- Maximum number of GET requests processed concurrently. This corresponds to the Alertmanager's `--web.get-concurrency` flag. format: int32 type: integer httpConfig: description: Defines HTTP parameters for web server. properties: headers: description: List of headers that can be added to HTTP responses. properties: contentSecurityPolicy: description: |- Set the Content-Security-Policy header to HTTP responses. Unset if blank. type: string strictTransportSecurity: description: |- Set the Strict-Transport-Security header to HTTP responses. Unset if blank. Please make sure that you use this with care as this header might force browsers to load Prometheus and the other applications hosted on the same domain and subdomains over HTTPS. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security type: string xContentTypeOptions: description: |- Set the X-Content-Type-Options header to HTTP responses. Unset if blank. Accepted value is nosniff. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options enum: - "" - NoSniff type: string xFrameOptions: description: |- Set the X-Frame-Options header to HTTP responses. Unset if blank. Accepted values are deny and sameorigin. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options enum: - "" - Deny - SameOrigin type: string xXSSProtection: description: |- Set the X-XSS-Protection header to all responses. Unset if blank. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection type: string type: object http2: description: |- Enable HTTP/2 support. Note that HTTP/2 is only supported with TLS. When TLSConfig is not configured, HTTP/2 will be disabled. Whenever the value of the field changes, a rolling update will be triggered. type: boolean type: object timeout: description: |- Timeout for HTTP requests. This corresponds to the Alertmanager's `--web.timeout` flag. format: int32 type: integer tlsConfig: description: Defines the TLS parameters for HTTPS. properties: cert: description: |- Secret or ConfigMap containing the TLS certificate for the web server. Either `keySecret` or `keyFile` must be defined. It is mutually exclusive with `certFile`. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object certFile: description: |- Path to the TLS certificate file in the container for the web server. Either `keySecret` or `keyFile` must be defined. It is mutually exclusive with `cert`. type: string cipherSuites: description: |- List of supported cipher suites for TLS versions up to TLS 1.2. If not defined, the Go default cipher suites are used. Available cipher suites are documented in the Go documentation: https://golang.org/pkg/crypto/tls/#pkg-constants items: type: string type: array client_ca: description: |- Secret or ConfigMap containing the CA certificate for client certificate authentication to the server. It is mutually exclusive with `clientCAFile`. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientAuthType: description: |- The server policy for client TLS authentication. For more detail on clientAuth options: https://golang.org/pkg/crypto/tls/#ClientAuthType type: string clientCAFile: description: |- Path to the CA certificate file for client certificate authentication to the server. It is mutually exclusive with `client_ca`. type: string curvePreferences: description: |- Elliptic curves that will be used in an ECDHE handshake, in preference order. Available curves are documented in the Go documentation: https://golang.org/pkg/crypto/tls/#CurveID items: type: string type: array keyFile: description: |- Path to the TLS private key file in the container for the web server. If defined, either `cert` or `certFile` must be defined. It is mutually exclusive with `keySecret`. type: string keySecret: description: |- Secret containing the TLS private key for the web server. Either `cert` or `certFile` must be defined. It is mutually exclusive with `keyFile`. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: Maximum TLS version that is acceptable. type: string minVersion: description: Minimum TLS version that is acceptable. type: string preferServerCipherSuites: description: |- Controls whether the server selects the client's most preferred cipher suite, or the server's most preferred cipher suite. If true then the server's preference, as expressed in the order of elements in cipherSuites, is used. type: boolean type: object type: object type: object status: description: |- Most recent observed status of the Alertmanager cluster. Read-only. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status properties: availableReplicas: description: |- Total number of available pods (ready for at least minReadySeconds) targeted by this Alertmanager cluster. format: int32 type: integer conditions: description: The current state of the Alertmanager object. items: description: |- Condition represents the state of the resources associated with the Prometheus, Alertmanager or ThanosRuler resource. properties: lastTransitionTime: description: lastTransitionTime is the time of the last update to the current status property. format: date-time type: string message: description: Human-readable message indicating details for the condition's last transition. 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[].observedGeneration` is 9, the condition is out of date with respect to the current state of the instance. format: int64 type: integer reason: description: Reason for the condition's last transition. type: string status: description: Status of the condition. minLength: 1 type: string type: description: Type of the condition being reported. minLength: 1 type: string required: - lastTransitionTime - status - type type: object type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map paused: description: |- Represents whether any actions on the underlying managed objects are being performed. Only delete actions will be performed. type: boolean replicas: description: |- Total number of non-terminated pods targeted by this Alertmanager object (their labels match the selector). format: int32 type: integer selector: description: The selector used to match the pods targeted by this Alertmanager object. type: string unavailableReplicas: description: Total number of unavailable pods targeted by this Alertmanager object. format: int32 type: integer updatedReplicas: description: |- Total number of non-terminated pods targeted by this Alertmanager object 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: scale: labelSelectorPath: .status.selector specReplicasPath: .spec.replicas statusReplicasPath: .status.replicas status: {} ================================================ FILE: hack/config/monitoring/crds/0podmonitorCustomResourceDefinition.yaml ================================================ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 operator.prometheus.io/version: 0.85.0 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: |- The `PodMonitor` custom resource definition (CRD) defines how `Prometheus` and `PrometheusAgent` can scrape metrics from a group of pods. Among other things, it allows to specify: * The pods to scrape via label selectors. * The container ports to scrape. * Authentication credentials to use. * Target and metric relabeling. `Prometheus` and `PrometheusAgent` objects select `PodMonitor` objects using label and namespace 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: Specification of desired Pod selection for target discovery by Prometheus. properties: attachMetadata: description: |- `attachMetadata` defines additional metadata which is added to the discovered targets. It requires Prometheus >= v2.35.0. properties: node: description: |- When set to true, Prometheus attaches node metadata to the discovered targets. The Prometheus service account must have the `list` and `watch` permissions on the `Nodes` objects. type: boolean type: object bodySizeLimit: description: |- When defined, bodySizeLimit specifies a job level limit on the size of uncompressed response body that will be accepted by Prometheus. It requires Prometheus >= v2.28.0. pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$ type: string convertClassicHistogramsToNHCB: description: |- Whether to convert all scraped classic histograms into a native histogram with custom buckets. It requires Prometheus >= v3.0.0. type: boolean fallbackScrapeProtocol: description: |- The protocol to use if a scrape returns blank, unparseable, or otherwise invalid Content-Type. It requires Prometheus >= v3.0.0. enum: - PrometheusProto - OpenMetricsText0.0.1 - OpenMetricsText1.0.0 - PrometheusText0.0.4 - PrometheusText1.0.0 type: string jobLabel: description: |- The label to use to retrieve the job name from. `jobLabel` selects the label from the associated Kubernetes `Pod` object which will be used as the `job` label for all metrics. For example if `jobLabel` is set to `foo` and the Kubernetes `Pod` object is labeled with `foo: bar`, then Prometheus adds the `job="bar"` label to all ingested metrics. If the value of this field is empty, the `job` label of the metrics defaults to the namespace and name of the PodMonitor object (e.g. `/`). type: string keepDroppedTargets: description: |- Per-scrape limit on the number of targets dropped by relabeling that will be kept in memory. 0 means no limit. It requires Prometheus >= v2.47.0. format: int64 type: integer labelLimit: description: |- Per-scrape limit on number of labels that will be accepted for a sample. It requires Prometheus >= v2.27.0. format: int64 type: integer labelNameLengthLimit: description: |- Per-scrape limit on length of labels name that will be accepted for a sample. It requires Prometheus >= v2.27.0. format: int64 type: integer labelValueLengthLimit: description: |- Per-scrape limit on length of labels value that will be accepted for a sample. It requires Prometheus >= v2.27.0. format: int64 type: integer namespaceSelector: description: |- `namespaceSelector` defines in which namespace(s) Prometheus should discover the pods. By default, the pods are discovered in the same namespace as the `PodMonitor` object but it is possible to select pods across different/all 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 to select from. items: type: string type: array type: object nativeHistogramBucketLimit: description: |- If there are more than this many buckets in a native histogram, buckets will be merged to stay within the limit. It requires Prometheus >= v2.45.0. format: int64 type: integer nativeHistogramMinBucketFactor: anyOf: - type: integer - type: string description: |- If the growth factor of one bucket to the next is smaller than this, buckets will be merged to increase the factor sufficiently. It requires Prometheus >= v2.50.0. pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true podMetricsEndpoints: description: Defines how to scrape metrics from the selected pods. items: description: |- PodMetricsEndpoint defines an endpoint serving Prometheus metrics to be scraped by Prometheus. properties: authorization: description: |- `authorization` configures the Authorization header credentials to use when scraping the target. Cannot be set at the same time as `basicAuth`, or `oauth2`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- `basicAuth` configures the Basic Authentication credentials to use when scraping the target. Cannot be set at the same time as `authorization`, or `oauth2`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenSecret: description: |- `bearerTokenSecret` specifies a key of a Secret containing the bearer token for scraping targets. The secret needs to be in the same namespace as the PodMonitor object and readable by the Prometheus Operator. Deprecated: use `authorization` instead. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic enableHttp2: description: '`enableHttp2` can be used to disable HTTP2 when scraping the target.' type: boolean filterRunning: description: |- When true, the pods which are not running (e.g. either in Failed or Succeeded state) are dropped during the target discovery. If unset, the filtering is enabled. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase type: boolean followRedirects: description: |- `followRedirects` defines whether the scrape requests should follow HTTP 3xx redirects. type: boolean honorLabels: description: |- When true, `honorLabels` preserves the metric's labels when they collide with the target's labels. type: boolean honorTimestamps: description: |- `honorTimestamps` controls whether Prometheus preserves the timestamps when exposed by the target. type: boolean interval: description: |- Interval at which Prometheus scrapes the metrics from the target. If empty, Prometheus uses the global scrape interval. 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: |- `metricRelabelings` configures the relabeling rules to apply to the samples before ingestion. items: description: |- RelabelConfig allows dynamic rewriting of the label set for targets, alerts, scraped samples and remote write samples. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. Regex capture groups are available. type: string type: object type: array noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- `oauth2` configures the OAuth2 settings to use when scraping the target. It requires Prometheus >= 2.27.0. Cannot be set at the same time as `authorization`, or `basicAuth`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures 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: '`params` define optional HTTP URL parameters.' type: object path: description: |- HTTP path from which to scrape for metrics. If empty, Prometheus uses the default value (e.g. `/metrics`). type: string port: description: |- The `Pod` port name which exposes the endpoint. It takes precedence over the `portNumber` and `targetPort` fields. type: string portNumber: description: The `Pod` port number which exposes the endpoint. format: int32 maximum: 65535 minimum: 1 type: integer proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string relabelings: description: |- `relabelings` configures the relabeling rules to apply the target's metadata labels. The 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. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. 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 Prometheus considers the scrape to be failed. If empty, Prometheus uses the global scrape timeout unless it is less than the target's scrape interval value in which the latter is used. The value cannot be greater than the scrape interval otherwise the operator will reject the resource. 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` object behind the Service, the port must be specified with container port property. Deprecated: use 'port' or 'portNumber' instead. x-kubernetes-int-or-string: true tlsConfig: description: TLS configuration to use when scraping the target. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object trackTimestampsStaleness: description: |- `trackTimestampsStaleness` defines whether Prometheus tracks staleness of the metrics that have an explicit timestamp present in scraped data. Has no effect if `honorTimestamps` is false. It requires Prometheus >= v2.48.0. type: boolean type: object type: array podTargetLabels: description: |- `podTargetLabels` defines the labels which are transferred from the associated Kubernetes `Pod` object onto the ingested metrics. items: type: string type: array sampleLimit: description: |- `sampleLimit` defines a per-scrape limit on the number of scraped samples that will be accepted. format: int64 type: integer scrapeClass: description: The scrape class to apply. minLength: 1 type: string scrapeClassicHistograms: description: |- Whether to scrape a classic histogram that is also exposed as a native histogram. It requires Prometheus >= v2.45.0. Notice: `scrapeClassicHistograms` corresponds to the `always_scrape_classic_histograms` field in the Prometheus configuration. type: boolean scrapeProtocols: description: |- `scrapeProtocols` defines the protocols to negotiate during a scrape. It tells clients the protocols supported by Prometheus in order of preference (from most to least preferred). If unset, Prometheus uses its default value. It requires Prometheus >= v2.49.0. items: description: |- ScrapeProtocol represents a protocol used by Prometheus for scraping metrics. Supported values are: * `OpenMetricsText0.0.1` * `OpenMetricsText1.0.0` * `PrometheusProto` * `PrometheusText0.0.4` * `PrometheusText1.0.0` enum: - PrometheusProto - OpenMetricsText0.0.1 - OpenMetricsText1.0.0 - PrometheusText0.0.4 - PrometheusText1.0.0 type: string type: array x-kubernetes-list-type: set selector: description: Label selector to select the Kubernetes `Pod` objects to scrape metrics from. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic selectorMechanism: description: |- Mechanism used to select the endpoints to scrape. By default, the selection process relies on relabel configurations to filter the discovered targets. Alternatively, you can opt in for role selectors, which may offer better efficiency in large clusters. Which strategy is best for your use case needs to be carefully evaluated. It requires Prometheus >= v2.17.0. enum: - RelabelConfig - RoleSelector type: string targetLimit: description: |- `targetLimit` defines a limit on the number of scraped targets that will be accepted. format: int64 type: integer required: - selector type: object required: - spec type: object served: true storage: true ================================================ FILE: hack/config/monitoring/crds/0probeCustomResourceDefinition.yaml ================================================ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 operator.prometheus.io/version: 0.85.0 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: |- The `Probe` custom resource definition (CRD) defines how to scrape metrics from prober exporters such as the [blackbox exporter](https://github.com/prometheus/blackbox_exporter). The `Probe` resource needs 2 pieces of information: * The list of probed addresses which can be defined statically or by discovering Kubernetes Ingress objects. * The prober which exposes the availability of probed endpoints (over various protocols such HTTP, TCP, ICMP, ...) as Prometheus metrics. `Prometheus` and `PrometheusAgent` objects select `Probe` objects using label and namespace 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: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. 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: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic convertClassicHistogramsToNHCB: description: |- Whether to convert all scraped classic histograms into a native histogram with custom buckets. It requires Prometheus >= v3.0.0. type: boolean fallbackScrapeProtocol: description: |- The protocol to use if a scrape returns blank, unparseable, or otherwise invalid Content-Type. It requires Prometheus >= v3.0.0. enum: - PrometheusProto - OpenMetricsText0.0.1 - OpenMetricsText1.0.0 - PrometheusText0.0.4 - PrometheusText1.0.0 type: string 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 keepDroppedTargets: description: |- Per-scrape limit on the number of targets dropped by relabeling that will be kept in memory. 0 means no limit. It requires Prometheus >= v2.47.0. format: int64 type: integer 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. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. 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 nativeHistogramBucketLimit: description: |- If there are more than this many buckets in a native histogram, buckets will be merged to stay within the limit. It requires Prometheus >= v2.45.0. format: int64 type: integer nativeHistogramMinBucketFactor: anyOf: - type: integer - type: string description: |- If the growth factor of one bucket to the next is smaller than this, buckets will be merged to increase the factor sufficiently. It requires Prometheus >= v2.50.0. pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true oauth2: description: OAuth2 for the URL. Only valid in Prometheus versions 2.27.0 and newer. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object params: description: |- The list of HTTP query parameters for the scrape. Please note that the `.spec.module` field takes precedence over the `module` parameter from this list when both are defined. The module name must be added using Module under ProbeSpec. items: description: ProbeParam defines specification of extra parameters for a Probe. properties: name: description: The parameter name minLength: 1 type: string values: description: The parameter values items: minLength: 1 type: string minItems: 1 type: array required: - name type: object minItems: 1 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map 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: noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string path: default: /probe description: |- Path to collect metrics from. Defaults to `/probe`. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ 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 scrapeClass: description: The scrape class to apply. minLength: 1 type: string scrapeClassicHistograms: description: |- Whether to scrape a classic histogram that is also exposed as a native histogram. It requires Prometheus >= v2.45.0. Notice: `scrapeClassicHistograms` corresponds to the `always_scrape_classic_histograms` field in the Prometheus configuration. type: boolean scrapeProtocols: description: |- `scrapeProtocols` defines the protocols to negotiate during a scrape. It tells clients the protocols supported by Prometheus in order of preference (from most to least preferred). If unset, Prometheus uses its default value. It requires Prometheus >= v2.49.0. items: description: |- ScrapeProtocol represents a protocol used by Prometheus for scraping metrics. Supported values are: * `OpenMetricsText0.0.1` * `OpenMetricsText1.0.0` * `PrometheusProto` * `PrometheusText0.0.4` * `PrometheusText1.0.0` enum: - PrometheusProto - OpenMetricsText0.0.1 - OpenMetricsText1.0.0 - PrometheusText0.0.4 - PrometheusText1.0.0 type: string type: array x-kubernetes-list-type: set scrapeTimeout: description: |- Timeout for scraping metrics from the Prometheus exporter. If not specified, the Prometheus global scrape timeout is used. The value cannot be greater than the scrape interval otherwise the operator will reject the resource. 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. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object required: - spec type: object served: true storage: true ================================================ FILE: hack/config/monitoring/crds/0prometheusCustomResourceDefinition.yaml ================================================ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 operator.prometheus.io/version: 0.85.0 name: prometheuses.monitoring.coreos.com spec: group: monitoring.coreos.com names: categories: - prometheus-operator kind: Prometheus listKind: PrometheusList plural: prometheuses shortNames: - prom singular: prometheus scope: Namespaced versions: - additionalPrinterColumns: - description: The version of Prometheus jsonPath: .spec.version name: Version type: string - description: The number of desired replicas jsonPath: .spec.replicas name: Desired type: integer - description: The number of ready replicas jsonPath: .status.availableReplicas name: Ready type: integer - jsonPath: .status.conditions[?(@.type == 'Reconciled')].status name: Reconciled type: string - jsonPath: .status.conditions[?(@.type == 'Available')].status name: Available type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - description: Whether the resource reconciliation is paused or not jsonPath: .status.paused name: Paused priority: 1 type: boolean name: v1 schema: openAPIV3Schema: description: |- The `Prometheus` custom resource definition (CRD) defines a desired [Prometheus](https://prometheus.io/docs/prometheus) setup to run in a Kubernetes cluster. It allows to specify many options such as the number of replicas, persistent storage, and Alertmanagers where firing alerts should be sent and many more. For each `Prometheus` resource, the Operator deploys one or several `StatefulSet` objects in the same namespace. The number of StatefulSets is equal to the number of shards which is 1 by default. The resource defines via label and namespace selectors which `ServiceMonitor`, `PodMonitor`, `Probe` and `PrometheusRule` objects should be associated to the deployed Prometheus instances. The Operator continuously reconciles the scrape and rules configuration and a sidecar container running in the Prometheus pods triggers a reload of the configuration when needed. 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 Prometheus cluster. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status properties: additionalAlertManagerConfigs: description: |- AdditionalAlertManagerConfigs specifies a key of a Secret containing additional Prometheus Alertmanager configurations. The Alertmanager configurations are appended to the configuration generated by the Prometheus Operator. They must be formatted according to the official Prometheus documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alertmanager_config The user is responsible for making sure that the configurations are valid Note that using this feature may expose the possibility to break upgrades of Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible AlertManager configs are going to break Prometheus after the upgrade. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic additionalAlertRelabelConfigs: description: |- AdditionalAlertRelabelConfigs specifies a key of a Secret containing additional Prometheus alert relabel configurations. The alert relabel configurations are appended to the configuration generated by the Prometheus Operator. They must be formatted according to the official Prometheus documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alert_relabel_configs The user is responsible for making sure that the configurations are valid Note that using this feature may expose the possibility to break upgrades of Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible alert relabel configs are going to break Prometheus after the upgrade. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic additionalArgs: description: |- AdditionalArgs allows setting additional arguments for the 'prometheus' container. It is intended for e.g. activating hidden flags which are not supported by the dedicated configuration options yet. The arguments are passed as-is to the Prometheus container which may cause issues if they are invalid or not supported by the given Prometheus version. In case of an argument conflict (e.g. an argument which is already set by the operator itself) or when providing an invalid argument, the reconciliation will fail and an error will be logged. items: description: Argument as part of the AdditionalArgs list. properties: name: description: Name of the argument, e.g. "scrape.discovery-reload-interval". minLength: 1 type: string value: description: Argument value, e.g. 30s. Can be empty for name-only arguments (e.g. --storage.tsdb.no-lockfile) type: string required: - name type: object type: array additionalScrapeConfigs: description: |- AdditionalScrapeConfigs allows specifying a key of a Secret containing additional Prometheus scrape configurations. Scrape configurations specified are appended to the configurations generated by the Prometheus Operator. Job configurations specified must have the form as specified in the official Prometheus documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config. 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 Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible scrape configs are going to break Prometheus after the upgrade. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic affinity: description: Defines the Pods' affinity scheduling rules if specified. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic type: object type: object alerting: description: Defines the settings related to Alertmanager. properties: alertmanagers: description: Alertmanager endpoints where Prometheus should send alerts to. items: description: |- AlertmanagerEndpoints defines a selection of a single Endpoints object containing Alertmanager IPs to fire alerts against. properties: alertRelabelings: description: |- Relabeling configs applied before sending alerts to a specific Alertmanager. It requires Prometheus >= v2.51.0. items: description: |- RelabelConfig allows dynamic rewriting of the label set for targets, alerts, scraped samples and remote write samples. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. Regex capture groups are available. type: string type: object type: array apiVersion: description: |- Version of the Alertmanager API that Prometheus uses to send alerts. It can be "V1" or "V2". The field has no effect for Prometheus >= v3.0.0 because only the v2 API is supported. enum: - v1 - V1 - v2 - V2 type: string authorization: description: |- Authorization section for Alertmanager. Cannot be set at the same time as `basicAuth`, `bearerTokenFile` or `sigv4`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth configuration for Alertmanager. Cannot be set at the same time as `bearerTokenFile`, `authorization` or `sigv4`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenFile: description: |- File to read bearer token for Alertmanager. Cannot be set at the same time as `basicAuth`, `authorization`, or `sigv4`. Deprecated: this will be removed in a future release. Prefer using `authorization`. type: string enableHttp2: description: Whether to enable HTTP2. type: boolean name: description: Name of the Endpoints object in the namespace. minLength: 1 type: string namespace: description: |- Namespace of the Endpoints object. If not set, the object will be discovered in the namespace of the Prometheus object. minLength: 1 type: string noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string pathPrefix: description: Prefix for the HTTP path alerts are pushed to. type: string port: anyOf: - type: integer - type: string description: Port on which the Alertmanager API is exposed. x-kubernetes-int-or-string: true proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string relabelings: description: Relabel configuration applied to the discovered Alertmanagers. items: description: |- RelabelConfig allows dynamic rewriting of the label set for targets, alerts, scraped samples and remote write samples. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. Regex capture groups are available. type: string type: object type: array scheme: description: Scheme to use when firing alerts. type: string sigv4: description: |- Sigv4 allows to configures AWS's Signature Verification 4 for the URL. It requires Prometheus >= v2.48.0. Cannot be set at the same time as `basicAuth`, `bearerTokenFile` or `authorization`. properties: accessKey: description: |- AccessKey is the AWS API key. If not specified, the environment variable `AWS_ACCESS_KEY_ID` is used. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic profile: description: Profile is the named AWS profile used to authenticate. type: string region: description: Region is the AWS region. If blank, the region from the default credentials chain used. type: string roleArn: description: RoleArn is the named AWS profile used to authenticate. type: string secretKey: description: |- SecretKey is the AWS API secret. If not specified, the environment variable `AWS_SECRET_ACCESS_KEY` is used. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object timeout: description: Timeout is a per-target Alertmanager timeout when pushing alerts. 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 tlsConfig: description: TLS Config to use for Alertmanager. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - name - port type: object type: array required: - alertmanagers type: object allowOverlappingBlocks: description: |- AllowOverlappingBlocks enables vertical compaction and vertical query merge in Prometheus. Deprecated: this flag has no effect for Prometheus >= 2.39.0 where overlapping blocks are enabled by default. type: boolean apiserverConfig: description: |- APIServerConfig allows specifying a host and auth methods to access the Kuberntees API server. If null, Prometheus is assumed to run inside of the cluster: it will discover the 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 section for the API server. Cannot be set at the same time as `basicAuth`, `bearerToken`, or `bearerTokenFile`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic credentialsFile: description: File to read a secret from, mutually exclusive with `credentials`. type: string type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth configuration for the API server. Cannot be set at the same time as `authorization`, `bearerToken`, or `bearerTokenFile`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerToken: description: |- *Warning: this field shouldn't be used because the token value appears in clear-text. Prefer using `authorization`.* Deprecated: this will be removed in a future release. type: string bearerTokenFile: description: |- File to read bearer token for accessing apiserver. Cannot be set at the same time as `basicAuth`, `authorization`, or `bearerToken`. Deprecated: this will be removed in a future release. Prefer using `authorization`. type: string host: description: |- Kubernetes API address consisting of a hostname or IP address followed by an optional port number. type: string noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS Config to use for the API server. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - host type: object arbitraryFSAccessThroughSMs: description: |- When true, ServiceMonitor, PodMonitor and Probe object are forbidden to reference arbitrary files on the file system of the 'prometheus' container. When a ServiceMonitor's endpoint specifies a `bearerTokenFile` value (e.g. '/var/run/secrets/kubernetes.io/serviceaccount/token'), a malicious target can get access to the Prometheus service account's token in the Prometheus' scrape request. Setting `spec.arbitraryFSAccessThroughSM` to 'true' would prevent the attack. Users should instead provide the credentials using the `spec.bearerTokenSecret` field. properties: deny: type: boolean type: object automountServiceAccountToken: description: |- AutomountServiceAccountToken indicates whether a service account token should be automatically mounted in the pod. If the field isn't set, the operator mounts the service account token by default. **Warning:** be aware that by default, Prometheus requires the service account token for Kubernetes service discovery. It is possible to use strategic merge patch to project the service account token into the 'prometheus' container. type: boolean baseImage: description: 'Deprecated: use ''spec.image'' instead.' type: string bodySizeLimit: description: |- BodySizeLimit defines per-scrape on response body size. Only valid in Prometheus versions 2.45.0 and newer. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedBodySizeLimit. pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$ type: string configMaps: description: |- ConfigMaps is a list of ConfigMaps in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. Each ConfigMap is added to the StatefulSet definition as a volume named `configmap-`. The ConfigMaps are mounted into /etc/prometheus/configmaps/ in the 'prometheus' container. items: type: string type: array containers: description: |- Containers allows injecting additional containers or modifying operator generated containers. This can be used to allow adding an authentication proxy to the Pods or to change the behavior of an operator generated container. Containers described here modify an operator generated container if they share the same name and modifications are done via a strategic merge patch. The names of containers managed by the operator are: * `prometheus` * `config-reloader` * `thanos-sidecar` Overriding containers 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. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: description: |- Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string description: Specifies the output format of the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: description: Selects a key of a secret in the pod's namespace properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map 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 or Secrets properties: configMapRef: description: The ConfigMap to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret must be defined type: boolean type: object x-kubernetes-map-type: atomic type: object type: array x-kubernetes-list-type: atomic 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 stopSignal: description: |- StopSignal defines which signal will be sent to a container when it is being stopped. If not specified, the default is defined by the container runtime in use. StopSignal can only be set for Pods with a non-empty .spec.os.name type: string 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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. This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: description: |- Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. type: string request: description: |- Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object 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 appArmorProfile: description: |- appArmorProfile is the AppArmor options to use by this container. If set, this profile overrides the pod's appArmorProfile. Note that this field cannot be set when spec.os.name is windows. properties: localhostProfile: description: |- localhostProfile indicates a profile loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost". type: string type: description: |- type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement. type: string required: - type type: object 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 x-kubernetes-list-type: atomic drop: description: Removed capabilities items: description: Capability represent POSIX capabilities type type: string type: array x-kubernetes-list-type: atomic 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 value is Default 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: 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 x-kubernetes-list-map-keys: - devicePath x-kubernetes-list-type: map 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. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None). 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 recursiveReadOnly: description: |- RecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled. type: string 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 x-kubernetes-list-map-keys: - mountPath x-kubernetes-list-type: map 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 convertClassicHistogramsToNHCB: description: |- Whether to convert all scraped classic histograms into a native histogram with custom buckets. It requires Prometheus >= v3.4.0. type: boolean disableCompaction: description: |- When true, the Prometheus compaction is disabled. When `spec.thanos.objectStorageConfig` or `spec.objectStorageConfigFile` are defined, the operator automatically disables block compaction to avoid race conditions during block uploads (as the Thanos documentation recommends). type: boolean dnsConfig: description: Defines the DNS configuration for the pods. properties: nameservers: description: |- A list of DNS name server IP addresses. This will be appended to the base nameservers generated from DNSPolicy. items: minLength: 1 type: string type: array x-kubernetes-list-type: set options: description: |- A list of DNS resolver options. This will be merged with the base options generated from DNSPolicy. 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: Name is required and must be unique. minLength: 1 type: string value: description: Value is optional. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map searches: description: |- A list of DNS search domains for host-name lookup. This will be appended to the base search paths generated from DNSPolicy. items: minLength: 1 type: string type: array x-kubernetes-list-type: set type: object dnsPolicy: description: Defines the DNS policy for the pods. enum: - ClusterFirstWithHostNet - ClusterFirst - Default - None type: string enableAdminAPI: description: |- Enables access to the Prometheus web admin API. WARNING: Enabling the admin APIs enables mutating endpoints, to delete data, shutdown Prometheus, and more. Enabling this should be done with care and the user is advised to add additional authentication authorization via a proxy to ensure only clients authorized to perform these actions can do so. For more information: https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis type: boolean enableFeatures: description: |- Enable access to Prometheus feature flags. By default, no features are enabled. Enabling features which are disabled by default 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. For more information see https://prometheus.io/docs/prometheus/latest/feature_flags/ items: minLength: 1 type: string type: array x-kubernetes-list-type: set enableOTLPReceiver: description: |- Enable Prometheus to be used as a receiver for the OTLP Metrics protocol. Note that the OTLP receiver endpoint is automatically enabled if `.spec.otlpConfig` is defined. It requires Prometheus >= v2.47.0. type: boolean enableRemoteWriteReceiver: description: |- Enable Prometheus to be used as a receiver for the Prometheus remote write protocol. WARNING: This is not considered an efficient way of ingesting samples. Use it with caution for specific low-volume use cases. It is not suitable for replacing the ingestion via scraping and turning Prometheus into a push-based metrics collection system. For more information see https://prometheus.io/docs/prometheus/latest/querying/api/#remote-write-receiver It requires Prometheus >= v2.33.0. type: boolean enableServiceLinks: description: Indicates whether information about services should be injected into pod's environment variables type: boolean enforcedBodySizeLimit: description: |- When defined, enforcedBodySizeLimit specifies a global limit on the size of uncompressed response body that will be accepted by Prometheus. Targets responding with a body larger than this many bytes will cause the scrape to fail. It requires Prometheus >= v2.28.0. When both `enforcedBodySizeLimit` and `bodySizeLimit` are defined and greater than zero, the following rules apply: * Scrape objects without a defined bodySizeLimit value will inherit the global bodySizeLimit value (Prometheus >= 2.45.0) or the enforcedBodySizeLimit value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedBodySizeLimit` is greater than the `bodySizeLimit`, the `bodySizeLimit` will be set to `enforcedBodySizeLimit`. * Scrape objects with a bodySizeLimit value less than or equal to enforcedBodySizeLimit keep their specific value. * Scrape objects with a bodySizeLimit value greater than enforcedBodySizeLimit are set to enforcedBodySizeLimit. pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$ type: string enforcedKeepDroppedTargets: description: |- When defined, enforcedKeepDroppedTargets specifies a global limit on the number of targets dropped by relabeling that will be kept in memory. The value overrides any `spec.keepDroppedTargets` set by ServiceMonitor, PodMonitor, Probe objects unless `spec.keepDroppedTargets` is greater than zero and less than `spec.enforcedKeepDroppedTargets`. It requires Prometheus >= v2.47.0. When both `enforcedKeepDroppedTargets` and `keepDroppedTargets` are defined and greater than zero, the following rules apply: * Scrape objects without a defined keepDroppedTargets value will inherit the global keepDroppedTargets value (Prometheus >= 2.45.0) or the enforcedKeepDroppedTargets value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedKeepDroppedTargets` is greater than the `keepDroppedTargets`, the `keepDroppedTargets` will be set to `enforcedKeepDroppedTargets`. * Scrape objects with a keepDroppedTargets value less than or equal to enforcedKeepDroppedTargets keep their specific value. * Scrape objects with a keepDroppedTargets value greater than enforcedKeepDroppedTargets are set to enforcedKeepDroppedTargets. format: int64 type: integer enforcedLabelLimit: description: |- When defined, enforcedLabelLimit specifies a global limit on the number of labels per sample. The value overrides any `spec.labelLimit` set by ServiceMonitor, PodMonitor, Probe objects unless `spec.labelLimit` is greater than zero and less than `spec.enforcedLabelLimit`. It requires Prometheus >= v2.27.0. When both `enforcedLabelLimit` and `labelLimit` are defined and greater than zero, the following rules apply: * Scrape objects without a defined labelLimit value will inherit the global labelLimit value (Prometheus >= 2.45.0) or the enforcedLabelLimit value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedLabelLimit` is greater than the `labelLimit`, the `labelLimit` will be set to `enforcedLabelLimit`. * Scrape objects with a labelLimit value less than or equal to enforcedLabelLimit keep their specific value. * Scrape objects with a labelLimit value greater than enforcedLabelLimit are set to enforcedLabelLimit. format: int64 type: integer enforcedLabelNameLengthLimit: description: |- When defined, enforcedLabelNameLengthLimit specifies a global limit on the length of labels name per sample. The value overrides any `spec.labelNameLengthLimit` set by ServiceMonitor, PodMonitor, Probe objects unless `spec.labelNameLengthLimit` is greater than zero and less than `spec.enforcedLabelNameLengthLimit`. It requires Prometheus >= v2.27.0. When both `enforcedLabelNameLengthLimit` and `labelNameLengthLimit` are defined and greater than zero, the following rules apply: * Scrape objects without a defined labelNameLengthLimit value will inherit the global labelNameLengthLimit value (Prometheus >= 2.45.0) or the enforcedLabelNameLengthLimit value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedLabelNameLengthLimit` is greater than the `labelNameLengthLimit`, the `labelNameLengthLimit` will be set to `enforcedLabelNameLengthLimit`. * Scrape objects with a labelNameLengthLimit value less than or equal to enforcedLabelNameLengthLimit keep their specific value. * Scrape objects with a labelNameLengthLimit value greater than enforcedLabelNameLengthLimit are set to enforcedLabelNameLengthLimit. format: int64 type: integer enforcedLabelValueLengthLimit: description: |- When not null, enforcedLabelValueLengthLimit defines a global limit on the length of labels value per sample. The value overrides any `spec.labelValueLengthLimit` set by ServiceMonitor, PodMonitor, Probe objects unless `spec.labelValueLengthLimit` is greater than zero and less than `spec.enforcedLabelValueLengthLimit`. It requires Prometheus >= v2.27.0. When both `enforcedLabelValueLengthLimit` and `labelValueLengthLimit` are defined and greater than zero, the following rules apply: * Scrape objects without a defined labelValueLengthLimit value will inherit the global labelValueLengthLimit value (Prometheus >= 2.45.0) or the enforcedLabelValueLengthLimit value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedLabelValueLengthLimit` is greater than the `labelValueLengthLimit`, the `labelValueLengthLimit` will be set to `enforcedLabelValueLengthLimit`. * Scrape objects with a labelValueLengthLimit value less than or equal to enforcedLabelValueLengthLimit keep their specific value. * Scrape objects with a labelValueLengthLimit value greater than enforcedLabelValueLengthLimit are set to enforcedLabelValueLengthLimit. format: int64 type: integer enforcedNamespaceLabel: description: |- When not empty, a label will be added to: 1. All metrics scraped from `ServiceMonitor`, `PodMonitor`, `Probe` and `ScrapeConfig` objects. 2. All metrics generated from recording rules defined in `PrometheusRule` objects. 3. All alerts generated from alerting rules defined in `PrometheusRule` objects. 4. All vector selectors of PromQL expressions defined in `PrometheusRule` objects. The label will not added for objects referenced in `spec.excludedFromEnforcement`. The label's name is this field's value. The label's value is the namespace of the `ServiceMonitor`, `PodMonitor`, `Probe`, `PrometheusRule` or `ScrapeConfig` object. type: string enforcedSampleLimit: description: |- When defined, enforcedSampleLimit specifies a global limit on the number of scraped samples that will be accepted. This overrides any `spec.sampleLimit` set by ServiceMonitor, PodMonitor, Probe objects unless `spec.sampleLimit` is greater than zero and less than `spec.enforcedSampleLimit`. It is meant to be used by admins to keep the overall number of samples/series under a desired limit. When both `enforcedSampleLimit` and `sampleLimit` are defined and greater than zero, the following rules apply: * Scrape objects without a defined sampleLimit value will inherit the global sampleLimit value (Prometheus >= 2.45.0) or the enforcedSampleLimit value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedSampleLimit` is greater than the `sampleLimit`, the `sampleLimit` will be set to `enforcedSampleLimit`. * Scrape objects with a sampleLimit value less than or equal to enforcedSampleLimit keep their specific value. * Scrape objects with a sampleLimit value greater than enforcedSampleLimit are set to enforcedSampleLimit. format: int64 type: integer enforcedTargetLimit: description: |- When defined, enforcedTargetLimit specifies a global limit on the number of scraped targets. The value overrides any `spec.targetLimit` set by ServiceMonitor, PodMonitor, Probe objects unless `spec.targetLimit` is greater than zero and less than `spec.enforcedTargetLimit`. It is meant to be used by admins to to keep the overall number of targets under a desired limit. When both `enforcedTargetLimit` and `targetLimit` are defined and greater than zero, the following rules apply: * Scrape objects without a defined targetLimit value will inherit the global targetLimit value (Prometheus >= 2.45.0) or the enforcedTargetLimit value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedTargetLimit` is greater than the `targetLimit`, the `targetLimit` will be set to `enforcedTargetLimit`. * Scrape objects with a targetLimit value less than or equal to enforcedTargetLimit keep their specific value. * Scrape objects with a targetLimit value greater than enforcedTargetLimit are set to enforcedTargetLimit. format: int64 type: integer evaluationInterval: default: 30s description: |- Interval between rule evaluations. Default: "30s" 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 excludedFromEnforcement: description: |- List of references to PodMonitor, ServiceMonitor, Probe and PrometheusRule objects to be excluded from enforcing a namespace label of origin. It is only applicable if `spec.enforcedNamespaceLabel` set to true. items: description: ObjectReference references a PodMonitor, ServiceMonitor, Probe or PrometheusRule object. properties: group: default: monitoring.coreos.com description: Group of the referent. When not specified, it defaults to `monitoring.coreos.com` enum: - monitoring.coreos.com type: string name: description: Name of the referent. When not set, all resources in the namespace are matched. type: string namespace: description: |- Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ minLength: 1 type: string resource: description: Resource of the referent. enum: - prometheusrules - servicemonitors - podmonitors - probes - scrapeconfigs type: string required: - namespace - resource type: object type: array exemplars: description: |- Exemplars related settings that are runtime reloadable. It requires to enable the `exemplar-storage` feature flag to be effective. properties: maxSize: description: |- Maximum number of exemplars stored in memory for all series. exemplar-storage itself must be enabled using the `spec.enableFeature` option for exemplars to be scraped in the first place. If not set, Prometheus uses its default value. A value of zero or less than zero disables the storage. format: int64 type: integer type: object externalLabels: additionalProperties: type: string description: |- The labels to add to any time series or alerts when communicating with external systems (federation, remote storage, Alertmanager). Labels defined by `spec.replicaExternalLabelName` and `spec.prometheusExternalLabelName` take precedence over this list. type: object externalUrl: description: |- The external URL under which the Prometheus service is externally available. This is necessary to generate correct URLs (for instance if Prometheus is accessible behind an Ingress resource). type: string hostAliases: description: |- Optional list of hosts and IPs that will be injected into the Pod's hosts file if specified. 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 required: - hostnames - ip type: object type: array x-kubernetes-list-map-keys: - ip x-kubernetes-list-type: map hostNetwork: description: |- Use the host's network namespace if true. Make sure to understand the security implications if you want to enable it (https://kubernetes.io/docs/concepts/configuration/overview/ ). When hostNetwork is enabled, this will set the DNS policy to `ClusterFirstWithHostNet` automatically (unless `.spec.DNSPolicy` is set to a different value). type: boolean hostUsers: description: |- HostUsers supports the user space in Kubernetes. More info: https://kubernetes.io/docs/tasks/configure-pod-container/user-namespaces/ The feature requires at least Kubernetes 1.28 with the `UserNamespacesSupport` feature gate enabled. Starting Kubernetes 1.33, the feature is enabled by default. type: boolean ignoreNamespaceSelectors: description: |- When true, `spec.namespaceSelector` from all PodMonitor, ServiceMonitor and Probe objects will be ignored. They will only discover targets within the namespace of the PodMonitor, ServiceMonitor and Probe object. type: boolean image: description: |- Container image name for Prometheus. If specified, it takes precedence over the `spec.baseImage`, `spec.tag` and `spec.sha` fields. Specifying `spec.version` is still necessary to ensure the Prometheus Operator knows which version of Prometheus is being configured. If neither `spec.image` nor `spec.baseImage` are defined, the operator will use the latest upstream version of Prometheus available at the time when the operator was released. type: string imagePullPolicy: description: |- Image pull policy for the 'prometheus', 'init-config-reloader' and 'config-reloader' containers. See https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy for more details. enum: - "" - Always - Never - IfNotPresent type: string imagePullSecrets: description: |- An optional list of references to Secrets in the same namespace to use for pulling images from registries. See http://kubernetes.io/docs/user-guide/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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string type: object x-kubernetes-map-type: atomic type: array initContainers: description: |- InitContainers allows injecting initContainers to the Pod definition. Those can be used to e.g. fetch secrets for injection into the Prometheus 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/ InitContainers described here modify an operator generated init containers if they share the same name and modifications are done via a strategic merge patch. The names of init container name managed by the operator are: * `init-config-reloader`. Overriding init containers 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. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: description: |- Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string description: Specifies the output format of the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: description: Selects a key of a secret in the pod's namespace properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map 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 or Secrets properties: configMapRef: description: The ConfigMap to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret must be defined type: boolean type: object x-kubernetes-map-type: atomic type: object type: array x-kubernetes-list-type: atomic 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 stopSignal: description: |- StopSignal defines which signal will be sent to a container when it is being stopped. If not specified, the default is defined by the container runtime in use. StopSignal can only be set for Pods with a non-empty .spec.os.name type: string 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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. This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: description: |- Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. type: string request: description: |- Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object 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 appArmorProfile: description: |- appArmorProfile is the AppArmor options to use by this container. If set, this profile overrides the pod's appArmorProfile. Note that this field cannot be set when spec.os.name is windows. properties: localhostProfile: description: |- localhostProfile indicates a profile loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost". type: string type: description: |- type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement. type: string required: - type type: object 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 x-kubernetes-list-type: atomic drop: description: Removed capabilities items: description: Capability represent POSIX capabilities type type: string type: array x-kubernetes-list-type: atomic 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 value is Default 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: 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 x-kubernetes-list-map-keys: - devicePath x-kubernetes-list-type: map 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. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None). 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 recursiveReadOnly: description: |- RecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled. type: string 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 x-kubernetes-list-map-keys: - mountPath x-kubernetes-list-type: map 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 keepDroppedTargets: description: |- Per-scrape limit on the number of targets dropped by relabeling that will be kept in memory. 0 means no limit. It requires Prometheus >= v2.47.0. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedKeepDroppedTargets. format: int64 type: integer labelLimit: description: |- Per-scrape limit on number of labels that will be accepted for a sample. Only valid in Prometheus versions 2.45.0 and newer. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedLabelLimit. 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.45.0 and newer. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedLabelNameLengthLimit. 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.45.0 and newer. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedLabelValueLengthLimit. format: int64 type: integer listenLocal: description: |- When true, the Prometheus server listens on the loopback address instead of the Pod IP's address. type: boolean logFormat: description: Log format for Log level for Prometheus and the config-reloader sidecar. enum: - "" - logfmt - json type: string logLevel: description: Log level for Prometheus and the config-reloader sidecar. enum: - "" - debug - info - warn - error type: string maximumStartupDurationSeconds: description: |- Defines the maximum time that the `prometheus` container's startup probe will wait before being considered failed. The startup probe will return success after the WAL replay is complete. If set, the value should be greater than 60 (seconds). Otherwise it will be equal to 600 seconds (15 minutes). format: int32 minimum: 60 type: integer minReadySeconds: description: |- Minimum number of seconds for which a newly created Pod should be ready without any of its container crashing for it to be considered available. If unset, pods will be considered available as soon as they are ready. format: int32 minimum: 0 type: integer nameEscapingScheme: description: |- Specifies the character escaping scheme that will be requested when scraping for metric and label names that do not conform to the legacy Prometheus character set. It requires Prometheus >= v3.4.0. enum: - AllowUTF8 - Underscores - Dots - Values type: string nameValidationScheme: description: |- Specifies the validation scheme for metric and label names. It requires Prometheus >= v2.55.0. enum: - UTF8 - Legacy type: string nodeSelector: additionalProperties: type: string description: Defines on which Nodes the Pods are scheduled. type: object otlp: description: |- Settings related to the OTLP receiver feature. It requires Prometheus >= v2.55.0. properties: convertHistogramsToNHCB: description: |- Configures optional translation of OTLP explicit bucket histograms into native histograms with custom buckets. It requires Prometheus >= v3.4.0. type: boolean ignoreResourceAttributes: description: |- List of OpenTelemetry resource attributes to ignore when `promoteAllResourceAttributes` is true. It requires `promoteAllResourceAttributes` to be true. It requires Prometheus >= v3.5.0. items: minLength: 1 type: string minItems: 1 type: array x-kubernetes-list-type: set keepIdentifyingResourceAttributes: description: |- Enables adding `service.name`, `service.namespace` and `service.instance.id` resource attributes to the `target_info` metric, on top of converting them into the `instance` and `job` labels. It requires Prometheus >= v3.1.0. type: boolean promoteAllResourceAttributes: description: |- Promote all resource attributes to metric labels except the ones defined in `ignoreResourceAttributes`. Cannot be true when `promoteResourceAttributes` is defined. It requires Prometheus >= v3.5.0. type: boolean promoteResourceAttributes: description: |- List of OpenTelemetry Attributes that should be promoted to metric labels, defaults to none. Cannot be defined when `promoteAllResourceAttributes` is true. items: minLength: 1 type: string minItems: 1 type: array x-kubernetes-list-type: set translationStrategy: description: |- Configures how the OTLP receiver endpoint translates the incoming metrics. It requires Prometheus >= v3.0.0. enum: - NoUTF8EscapingWithSuffixes - UnderscoreEscapingWithSuffixes - NoTranslation type: string type: object overrideHonorLabels: description: |- When true, Prometheus resolves label conflicts by renaming the labels in the scraped data to “exported_” for all targets created from ServiceMonitor, PodMonitor and ScrapeConfig objects. Otherwise the HonorLabels field of the service or pod monitor applies. In practice,`overrideHonorLaels:true` enforces `honorLabels:false` for all ServiceMonitor, PodMonitor and ScrapeConfig objects. type: boolean overrideHonorTimestamps: description: |- When true, Prometheus ignores the timestamps for all the targets created from service and pod monitors. Otherwise the HonorTimestamps field of the service or pod monitor applies. type: boolean paused: description: |- When a Prometheus deployment is paused, no actions except for deletion will be performed on the underlying objects. type: boolean persistentVolumeClaimRetentionPolicy: description: |- The field controls if and how PVCs are deleted during the lifecycle of a StatefulSet. The default behavior is all PVCs are retained. This is an alpha field from kubernetes 1.23 until 1.26 and a beta field from 1.26. It requires enabling the StatefulSetAutoDeletePVC feature gate. properties: whenDeleted: description: |- WhenDeleted specifies what happens to PVCs created from StatefulSet VolumeClaimTemplates when the StatefulSet is deleted. The default policy of `Retain` causes PVCs to not be affected by StatefulSet deletion. The `Delete` policy causes those PVCs to be deleted. type: string whenScaled: description: |- WhenScaled specifies what happens to PVCs created from StatefulSet VolumeClaimTemplates when the StatefulSet is scaled down. The default policy of `Retain` causes PVCs to not be affected by a scaledown. The `Delete` policy causes the associated PVCs for any excess pods above the replica count to be deleted. type: string type: object podMetadata: description: |- PodMetadata configures labels and annotations which are propagated to the Prometheus pods. The following items are reserved and cannot be overridden: * "prometheus" label, set to the name of the Prometheus object. * "app.kubernetes.io/instance" label, set to the name of the Prometheus object. * "app.kubernetes.io/managed-by" label, set to "prometheus-operator". * "app.kubernetes.io/name" label, set to "prometheus". * "app.kubernetes.io/version" label, set to the Prometheus version. * "operator.prometheus.io/name" label, set to the name of the Prometheus object. * "operator.prometheus.io/shard" label, set to the shard number of the Prometheus object. * "kubectl.kubernetes.io/default-container" annotation, set to "prometheus". 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. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/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: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/ type: string type: object podMonitorNamespaceSelector: description: |- Namespaces to match for PodMonitors discovery. An empty label selector matches all namespaces. A null label selector (default value) matches the current namespace only. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic podMonitorSelector: description: |- PodMonitors to be selected for target discovery. An empty label selector matches all objects. A null label selector matches no objects. If `spec.serviceMonitorSelector`, `spec.podMonitorSelector`, `spec.probeSelector` and `spec.scrapeConfigSelector` are null, the Prometheus configuration is unmanaged. The Prometheus operator will ensure that the Prometheus configuration's Secret exists, but it is the responsibility of the user to provide the raw gzipped Prometheus configuration under the `prometheus.yaml.gz` key. This behavior is *deprecated* and will be removed in the next major version of the custom resource definition. It is recommended to use `spec.additionalScrapeConfigs` instead. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic podTargetLabels: description: |- PodTargetLabels are appended to the `spec.podTargetLabels` field of all PodMonitor and ServiceMonitor objects. items: type: string type: array portName: default: web description: |- Port name used for the pods and governing service. Default: "web" type: string priorityClassName: description: Priority class assigned to the Pods. type: string probeNamespaceSelector: description: |- Namespaces to match for Probe discovery. An empty label selector matches all namespaces. A null label selector matches the current namespace only. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic probeSelector: description: |- Probes to be selected for target discovery. An empty label selector matches all objects. A null label selector matches no objects. If `spec.serviceMonitorSelector`, `spec.podMonitorSelector`, `spec.probeSelector` and `spec.scrapeConfigSelector` are null, the Prometheus configuration is unmanaged. The Prometheus operator will ensure that the Prometheus configuration's Secret exists, but it is the responsibility of the user to provide the raw gzipped Prometheus configuration under the `prometheus.yaml.gz` key. This behavior is *deprecated* and will be removed in the next major version of the custom resource definition. It is recommended to use `spec.additionalScrapeConfigs` instead. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic prometheusExternalLabelName: description: |- Name of Prometheus external label used to denote the Prometheus instance name. The external label will _not_ be added when the field is set to the empty string (`""`). Default: "prometheus" type: string prometheusRulesExcludedFromEnforce: description: |- Defines the list of PrometheusRule objects to which the namespace label enforcement doesn't apply. This is only relevant when `spec.enforcedNamespaceLabel` is set to true. Deprecated: use `spec.excludedFromEnforcement` instead. items: description: |- PrometheusRuleExcludeConfig enables users to configure excluded PrometheusRule names and their namespaces to be ignored while enforcing namespace label for alerts and metrics. properties: ruleName: description: Name of the excluded PrometheusRule object. type: string ruleNamespace: description: Namespace of the excluded PrometheusRule object. type: string required: - ruleName - ruleNamespace type: object type: array query: description: QuerySpec defines the configuration of the Promethus query service. properties: lookbackDelta: description: The delta difference allowed for retrieving metrics during expression evaluations. type: string maxConcurrency: description: Number of concurrent queries that can be run at once. format: int32 minimum: 1 type: integer maxSamples: description: |- Maximum number of samples a single query can load into memory. Note that queries will fail if they would load more samples than this into memory, so this also limits the number of samples a query can return. format: int32 type: integer timeout: description: Maximum time a query may take before being aborted. 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 type: object queryLogFile: description: |- queryLogFile specifies where the file to which PromQL queries are logged. If the filename has an empty path, e.g. 'query.log', The Prometheus Pods will mount the file into an emptyDir volume at `/var/log/prometheus`. If a full path is provided, e.g. '/var/log/prometheus/query.log', you must mount a volume in the specified directory and it must be writable. This is because the prometheus container runs with a read-only root filesystem for security reasons. Alternatively, the location can be set to a standard I/O stream, e.g. `/dev/stdout`, to log query information to the default Prometheus log stream. type: string reloadStrategy: description: |- Defines the strategy used to reload the Prometheus configuration. If not specified, the configuration is reloaded using the /-/reload HTTP endpoint. enum: - HTTP - ProcessSignal type: string remoteRead: description: Defines the list of remote read configurations. items: description: |- RemoteReadSpec defines the configuration for Prometheus to read back samples from a remote endpoint. properties: authorization: description: |- Authorization section for the URL. It requires Prometheus >= v2.26.0. Cannot be set at the same time as `basicAuth`, or `oauth2`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic credentialsFile: description: File to read a secret from, mutually exclusive with `credentials`. type: string type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth configuration for the URL. Cannot be set at the same time as `authorization`, or `oauth2`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerToken: description: |- *Warning: this field shouldn't be used because the token value appears in clear-text. Prefer using `authorization`.* Deprecated: this will be removed in a future release. type: string bearerTokenFile: description: |- File from which to read the bearer token for the URL. Deprecated: this will be removed in a future release. Prefer using `authorization`. type: string filterExternalLabels: description: |- Whether to use the external labels as selectors for the remote read endpoint. It requires Prometheus >= v2.34.0. type: boolean followRedirects: description: |- Configure whether HTTP requests follow HTTP 3xx redirects. It requires Prometheus >= v2.26.0. type: boolean headers: additionalProperties: type: string description: |- Custom HTTP headers to be sent along with each remote read request. Be aware that headers that are set by Prometheus itself can't be overwritten. Only valid in Prometheus versions 2.26.0 and newer. type: object name: description: |- The name of the remote read queue, it must be unique if specified. The name is used in metrics and logging in order to differentiate read configurations. It requires Prometheus >= v2.15.0. type: string noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- OAuth2 configuration for the URL. It requires Prometheus >= v2.27.0. Cannot be set at the same time as `authorization`, or `basicAuth`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string readRecent: description: |- Whether reads should be made for queries for time ranges that the local storage should have complete data for. type: boolean remoteTimeout: description: Timeout for requests to the remote read endpoint. 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 requiredMatchers: additionalProperties: type: string description: |- An optional list of equality matchers which have to be present in a selector to query the remote read endpoint. type: object tlsConfig: description: TLS Config to use for the URL. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object url: description: The URL of the endpoint to query from. type: string required: - url type: object type: array remoteWrite: description: Defines the list of remote write configurations. items: description: |- RemoteWriteSpec defines the configuration to write samples from Prometheus to a remote endpoint. properties: authorization: description: |- Authorization section for the URL. It requires Prometheus >= v2.26.0 or Thanos >= v0.24.0. Cannot be set at the same time as `sigv4`, `basicAuth`, `oauth2`, or `azureAd`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic credentialsFile: description: File to read a secret from, mutually exclusive with `credentials`. type: string type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object azureAd: description: |- AzureAD for the URL. It requires Prometheus >= v2.45.0 or Thanos >= v0.31.0. Cannot be set at the same time as `authorization`, `basicAuth`, `oauth2`, or `sigv4`. properties: cloud: description: The Azure Cloud. Options are 'AzurePublic', 'AzureChina', or 'AzureGovernment'. enum: - AzureChina - AzureGovernment - AzurePublic type: string managedIdentity: description: |- ManagedIdentity defines the Azure User-assigned Managed identity. Cannot be set at the same time as `oauth` or `sdk`. properties: clientId: description: The client id type: string required: - clientId type: object oauth: description: |- OAuth defines the oauth config that is being used to authenticate. Cannot be set at the same time as `managedIdentity` or `sdk`. It requires Prometheus >= v2.48.0 or Thanos >= v0.31.0. properties: clientId: description: '`clientID` is the clientId of the Azure Active Directory application that is being used to authenticate.' minLength: 1 type: string clientSecret: description: '`clientSecret` specifies a key of a Secret containing the client secret of the Azure Active Directory application that is being used to authenticate.' properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic tenantId: description: '`tenantId` is the tenant ID of the Azure Active Directory application that is being used to authenticate.' minLength: 1 pattern: ^[0-9a-zA-Z-.]+$ type: string required: - clientId - clientSecret - tenantId type: object sdk: description: |- SDK defines the Azure SDK config that is being used to authenticate. See https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication Cannot be set at the same time as `oauth` or `managedIdentity`. It requires Prometheus >= v2.52.0 or Thanos >= v0.36.0. properties: tenantId: description: '`tenantId` is the tenant ID of the azure active directory application that is being used to authenticate.' pattern: ^[0-9a-zA-Z-.]+$ type: string type: object type: object basicAuth: description: |- BasicAuth configuration for the URL. Cannot be set at the same time as `sigv4`, `authorization`, `oauth2`, or `azureAd`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerToken: description: |- *Warning: this field shouldn't be used because the token value appears in clear-text. Prefer using `authorization`.* Deprecated: this will be removed in a future release. type: string bearerTokenFile: description: |- File from which to read bearer token for the URL. Deprecated: this will be removed in a future release. Prefer using `authorization`. type: string enableHTTP2: description: Whether to enable HTTP2. type: boolean followRedirects: description: |- Configure whether HTTP requests follow HTTP 3xx redirects. It requires Prometheus >= v2.26.0 or Thanos >= v0.24.0. type: boolean headers: additionalProperties: type: string description: |- Custom HTTP headers to be sent along with each remote write request. Be aware that headers that are set by Prometheus itself can't be overwritten. It requires Prometheus >= v2.25.0 or Thanos >= v0.24.0. type: object messageVersion: description: |- The Remote Write message's version to use when writing to the endpoint. `Version1.0` corresponds to the `prometheus.WriteRequest` protobuf message introduced in Remote Write 1.0. `Version2.0` corresponds to the `io.prometheus.write.v2.Request` protobuf message introduced in Remote Write 2.0. When `Version2.0` is selected, Prometheus will automatically be configured to append the metadata of scraped metrics to the WAL. Before setting this field, consult with your remote storage provider what message version it supports. It requires Prometheus >= v2.54.0 or Thanos >= v0.37.0. enum: - V1.0 - V2.0 type: string metadataConfig: description: MetadataConfig configures the sending of series metadata to the remote storage. properties: maxSamplesPerSend: description: |- MaxSamplesPerSend is the maximum number of metadata samples per send. It requires Prometheus >= v2.29.0. format: int32 minimum: -1 type: integer send: description: Defines whether metric metadata is sent to the remote storage or not. type: boolean sendInterval: description: Defines how frequently metric metadata is sent to the remote storage. 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 type: object name: description: |- The name of the remote write queue, it must be unique if specified. The name is used in metrics and logging in order to differentiate queues. It requires Prometheus >= v2.15.0 or Thanos >= 0.24.0. type: string noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- OAuth2 configuration for the URL. It requires Prometheus >= v2.27.0 or Thanos >= v0.24.0. Cannot be set at the same time as `sigv4`, `authorization`, `basicAuth`, or `azureAd`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string queueConfig: description: QueueConfig allows tuning of the remote write queue parameters. properties: batchSendDeadline: description: BatchSendDeadline is the maximum time a sample will wait in buffer. 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 capacity: description: |- Capacity is the number of samples to buffer per shard before we start dropping them. type: integer maxBackoff: description: MaxBackoff is the maximum retry delay. 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 maxRetries: description: MaxRetries is the maximum number of times to retry a batch on recoverable errors. type: integer maxSamplesPerSend: description: MaxSamplesPerSend is the maximum number of samples per send. type: integer maxShards: description: MaxShards is the maximum number of shards, i.e. amount of concurrency. type: integer minBackoff: description: MinBackoff is the initial retry delay. Gets doubled for every retry. 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 minShards: description: MinShards is the minimum number of shards, i.e. amount of concurrency. type: integer retryOnRateLimit: description: |- Retry upon receiving a 429 status code from the remote-write storage. This is an *experimental feature*, it may change in any upcoming release in a breaking way. type: boolean sampleAgeLimit: description: |- SampleAgeLimit drops samples older than the limit. It requires Prometheus >= v2.50.0 or Thanos >= v0.32.0. 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 type: object remoteTimeout: description: Timeout for requests to the remote write endpoint. 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 roundRobinDNS: description: |- When enabled: - The remote-write mechanism will resolve the hostname via DNS. - It will randomly select one of the resolved IP addresses and connect to it. When disabled (default behavior): - The Go standard library will handle hostname resolution. - It will attempt connections to each resolved IP address sequentially. Note: The connection timeout applies to the entire resolution and connection process. If disabled, the timeout is distributed across all connection attempts. It requires Prometheus >= v3.1.0 or Thanos >= v0.38.0. type: boolean sendExemplars: description: |- Enables sending of exemplars over remote write. Note that exemplar-storage itself must be enabled using the `spec.enableFeatures` option for exemplars to be scraped in the first place. It requires Prometheus >= v2.27.0 or Thanos >= v0.24.0. type: boolean sendNativeHistograms: description: |- Enables sending of native histograms, also known as sparse histograms over remote write. It requires Prometheus >= v2.40.0 or Thanos >= v0.30.0. type: boolean sigv4: description: |- Sigv4 allows to configures AWS's Signature Verification 4 for the URL. It requires Prometheus >= v2.26.0 or Thanos >= v0.24.0. Cannot be set at the same time as `authorization`, `basicAuth`, `oauth2`, or `azureAd`. properties: accessKey: description: |- AccessKey is the AWS API key. If not specified, the environment variable `AWS_ACCESS_KEY_ID` is used. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic profile: description: Profile is the named AWS profile used to authenticate. type: string region: description: Region is the AWS region. If blank, the region from the default credentials chain used. type: string roleArn: description: RoleArn is the named AWS profile used to authenticate. type: string secretKey: description: |- SecretKey is the AWS API secret. If not specified, the environment variable `AWS_SECRET_ACCESS_KEY` is used. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object tlsConfig: description: TLS Config to use for the URL. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object url: description: The URL of the endpoint to send samples to. minLength: 1 type: string writeRelabelConfigs: description: The list of remote write relabel configurations. items: description: |- RelabelConfig allows dynamic rewriting of the label set for targets, alerts, scraped samples and remote write samples. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. Regex capture groups are available. type: string type: object type: array required: - url type: object type: array remoteWriteReceiverMessageVersions: description: |- List of the protobuf message versions to accept when receiving the remote writes. It requires Prometheus >= v2.54.0. items: enum: - V1.0 - V2.0 type: string minItems: 1 type: array x-kubernetes-list-type: set replicaExternalLabelName: description: |- Name of Prometheus external label used to denote the replica name. The external label will _not_ be added when the field is set to the empty string (`""`). Default: "prometheus_replica" type: string replicas: description: |- Number of replicas of each shard to deploy for a Prometheus deployment. `spec.replicas` multiplied by `spec.shards` is the total number of Pods created. Default: 1 format: int32 type: integer resources: description: Defines the resources requests and limits of the 'prometheus' container. properties: claims: description: |- Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: description: |- Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. type: string request: description: |- Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object retention: description: |- How long to retain the Prometheus data. Default: "24h" if `spec.retention` and `spec.retentionSize` are empty. 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 retentionSize: description: Maximum number of bytes used by the Prometheus data. pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$ type: string routePrefix: description: |- The route prefix Prometheus registers HTTP handlers for. This is useful when using `spec.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 ruleNamespaceSelector: description: |- Namespaces to match for PrometheusRule discovery. An empty label selector matches all namespaces. A null label selector matches the current namespace only. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic ruleQueryOffset: description: |- Defines the offset the rule evaluation timestamp of this particular group by the specified duration into the past. It requires Prometheus >= v2.53.0. 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 ruleSelector: description: |- PrometheusRule objects to be selected for rule evaluation. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic rules: description: Defines the configuration of the Prometheus rules' engine. properties: alert: description: |- Defines the parameters of the Prometheus rules' engine. Any update to these parameters trigger a restart of the pods. properties: forGracePeriod: description: |- Minimum duration between alert and restored 'for' state. This is maintained only for alerts with a configured 'for' time greater than the grace period. type: string forOutageTolerance: description: |- Max time to tolerate prometheus outage for restoring 'for' state of alert. type: string resendDelay: description: |- Minimum amount of time to wait before resending an alert to Alertmanager. type: string type: object type: object runtime: description: RuntimeConfig configures the values for the Prometheus process behavior properties: goGC: description: |- The Go garbage collection target percentage. Lowering this number may increase the CPU usage. See: https://tip.golang.org/doc/gc-guide#GOGC format: int32 minimum: -1 type: integer type: object sampleLimit: description: |- SampleLimit defines per-scrape limit on number of scraped samples that will be accepted. Only valid in Prometheus versions 2.45.0 and newer. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedSampleLimit. format: int64 type: integer scrapeClasses: description: |- List of scrape classes to expose to scraping objects such as PodMonitors, ServiceMonitors, Probes and ScrapeConfigs. This is an *experimental feature*, it may change in any upcoming release in a breaking way. items: properties: attachMetadata: description: |- AttachMetadata configures additional metadata to the discovered targets. When the scrape object defines its own configuration, it takes precedence over the scrape class configuration. properties: node: description: |- When set to true, Prometheus attaches node metadata to the discovered targets. The Prometheus service account must have the `list` and `watch` permissions on the `Nodes` objects. type: boolean type: object authorization: description: |- Authorization section for the ScrapeClass. It will only apply if the scrape resource doesn't specify any Authorization. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic credentialsFile: description: File to read a secret from, mutually exclusive with `credentials`. type: string type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object default: description: |- Default indicates that the scrape applies to all scrape objects that don't configure an explicit scrape class name. Only one scrape class can be set as the default. type: boolean fallbackScrapeProtocol: description: |- The protocol to use if a scrape returns blank, unparseable, or otherwise invalid Content-Type. It will only apply if the scrape resource doesn't specify any FallbackScrapeProtocol It requires Prometheus >= v3.0.0. enum: - PrometheusProto - OpenMetricsText0.0.1 - OpenMetricsText1.0.0 - PrometheusText0.0.4 - PrometheusText1.0.0 type: string metricRelabelings: description: |- MetricRelabelings configures the relabeling rules to apply to all samples before ingestion. The Operator adds the scrape class metric relabelings defined here. Then the Operator adds the target-specific metric relabelings defined in ServiceMonitors, PodMonitors, Probes and ScrapeConfigs. Then the Operator adds namespace enforcement relabeling rule, specified in '.spec.enforcedNamespaceLabel'. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs items: description: |- RelabelConfig allows dynamic rewriting of the label set for targets, alerts, scraped samples and remote write samples. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. Regex capture groups are available. type: string type: object type: array name: description: Name of the scrape class. minLength: 1 type: string relabelings: description: |- Relabelings configures the relabeling rules to apply to all scrape targets. The Operator automatically adds relabelings for a few standard Kubernetes fields like `__meta_kubernetes_namespace` and `__meta_kubernetes_service_name`. Then the Operator adds the scrape class relabelings defined here. Then the Operator adds the target-specific relabelings defined in the scrape object. 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. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. Regex capture groups are available. type: string type: object type: array tlsConfig: description: |- TLSConfig defines the TLS settings to use for the scrape. When the scrape objects define their own CA, certificate and/or key, they take precedence over the corresponding scrape class fields. For now only the `caFile`, `certFile` and `keyFile` fields are supported. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map scrapeClassicHistograms: description: |- Whether to scrape a classic histogram that is also exposed as a native histogram. Notice: `scrapeClassicHistograms` corresponds to the `always_scrape_classic_histograms` field in the Prometheus configuration. It requires Prometheus >= v3.5.0. type: boolean scrapeConfigNamespaceSelector: description: |- Namespaces to match for ScrapeConfig discovery. An empty label selector matches all namespaces. A null label selector matches the current namespace only. Note that the ScrapeConfig custom resource definition is currently at Alpha level. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic scrapeConfigSelector: description: |- ScrapeConfigs to be selected for target discovery. An empty label selector matches all objects. A null label selector matches no objects. If `spec.serviceMonitorSelector`, `spec.podMonitorSelector`, `spec.probeSelector` and `spec.scrapeConfigSelector` are null, the Prometheus configuration is unmanaged. The Prometheus operator will ensure that the Prometheus configuration's Secret exists, but it is the responsibility of the user to provide the raw gzipped Prometheus configuration under the `prometheus.yaml.gz` key. This behavior is *deprecated* and will be removed in the next major version of the custom resource definition. It is recommended to use `spec.additionalScrapeConfigs` instead. Note that the ScrapeConfig custom resource definition is currently at Alpha level. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic scrapeFailureLogFile: description: |- File to which scrape failures are logged. Reloading the configuration will reopen the file. If the filename has an empty path, e.g. 'file.log', The Prometheus Pods will mount the file into an emptyDir volume at `/var/log/prometheus`. If a full path is provided, e.g. '/var/log/prometheus/file.log', you must mount a volume in the specified directory and it must be writable. It requires Prometheus >= v2.55.0. minLength: 1 type: string scrapeInterval: default: 30s description: |- Interval between consecutive scrapes. Default: "30s" 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 scrapeProtocols: description: |- The protocols to negotiate during a scrape. It tells clients the protocols supported by Prometheus in order of preference (from most to least preferred). If unset, Prometheus uses its default value. It requires Prometheus >= v2.49.0. `PrometheusText1.0.0` requires Prometheus >= v3.0.0. items: description: |- ScrapeProtocol represents a protocol used by Prometheus for scraping metrics. Supported values are: * `OpenMetricsText0.0.1` * `OpenMetricsText1.0.0` * `PrometheusProto` * `PrometheusText0.0.4` * `PrometheusText1.0.0` enum: - PrometheusProto - OpenMetricsText0.0.1 - OpenMetricsText1.0.0 - PrometheusText0.0.4 - PrometheusText1.0.0 type: string type: array x-kubernetes-list-type: set scrapeTimeout: description: |- Number of seconds to wait until a scrape request times out. The value cannot be greater than the scrape interval otherwise the operator will reject the resource. 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 secrets: description: |- Secrets is a list of Secrets in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. Each Secret is added to the StatefulSet definition as a volume named `secret-`. The Secrets are mounted into /etc/prometheus/secrets/ in the 'prometheus' container. items: type: string type: array x-kubernetes-list-type: set securityContext: description: |- SecurityContext holds pod-level security attributes and common container settings. This defaults to the default PodSecurityContext. properties: appArmorProfile: description: |- appArmorProfile is the AppArmor 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 loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost". type: string type: description: |- type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement. type: string required: - type type: object 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: 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---- 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 seLinuxChangePolicy: description: |- seLinuxChangePolicy defines how the container's SELinux label is applied to all volumes used by the Pod. It has no effect on nodes that do not support SELinux or to volumes does not support SELinux. Valid values are "MountOption" and "Recursive". "Recursive" means relabeling of all files on all Pod volumes by the container runtime. This may be slow for large volumes, but allows mixing privileged and unprivileged Pods sharing the same volume on the same node. "MountOption" mounts all eligible Pod volumes with `-o context` mount option. This requires all Pods that share the same volume to use the same SELinux label. It is not possible to share the same volume among privileged and unprivileged Pods. Eligible volumes are in-tree FibreChannel and iSCSI volumes, and all CSI volumes whose CSI driver announces SELinux support by setting spec.seLinuxMount: true in their CSIDriver instance. Other volumes are always re-labelled recursively. "MountOption" value is allowed only when SELinuxMount feature gate is enabled. If not specified and SELinuxMount feature gate is enabled, "MountOption" is used. If not specified and SELinuxMount feature gate is disabled, "MountOption" is used for ReadWriteOncePod volumes and "Recursive" for all other volumes. This field affects only Pods that have SELinux label set, either in PodSecurityContext or in SecurityContext of all containers. All Pods that use the same volume should use the same seLinuxChangePolicy, otherwise some pods can get stuck in ContainerCreating state. Note that this field cannot be set when spec.os.name is windows. type: string 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: 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 and fsGroup (if specified). If the SupplementalGroupsPolicy feature is enabled, the supplementalGroupsPolicy field determines whether these are in addition to or instead of any group memberships defined in the container image. If unspecified, no additional groups are added, though group memberships defined in the container image may still be used, depending on the supplementalGroupsPolicy field. Note that this field cannot be set when spec.os.name is windows. items: format: int64 type: integer type: array x-kubernetes-list-type: atomic supplementalGroupsPolicy: description: |- Defines how supplemental groups of the first container processes are calculated. Valid values are "Merge" and "Strict". If not specified, "Merge" is used. (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled and the container runtime must implement support for this feature. Note that this field cannot be set when spec.os.name is windows. type: string 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 x-kubernetes-list-type: atomic 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 serviceAccountName: description: |- ServiceAccountName is the name of the ServiceAccount to use to run the Prometheus Pods. type: string serviceDiscoveryRole: description: |- Defines the service discovery role used to discover targets from `ServiceMonitor` objects and Alertmanager endpoints. If set, the value should be either "Endpoints" or "EndpointSlice". If unset, the operator assumes the "Endpoints" role. enum: - Endpoints - EndpointSlice type: string serviceMonitorNamespaceSelector: description: |- Namespaces to match for ServicedMonitors discovery. An empty label selector matches all namespaces. A null label selector (default value) matches the current namespace only. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic serviceMonitorSelector: description: |- ServiceMonitors to be selected for target discovery. An empty label selector matches all objects. A null label selector matches no objects. If `spec.serviceMonitorSelector`, `spec.podMonitorSelector`, `spec.probeSelector` and `spec.scrapeConfigSelector` are null, the Prometheus configuration is unmanaged. The Prometheus operator will ensure that the Prometheus configuration's Secret exists, but it is the responsibility of the user to provide the raw gzipped Prometheus configuration under the `prometheus.yaml.gz` key. This behavior is *deprecated* and will be removed in the next major version of the custom resource definition. It is recommended to use `spec.additionalScrapeConfigs` instead. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic serviceName: description: |- The name of the service name used by the underlying StatefulSet(s) as the governing service. If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels. If empty, the operator will create and manage a headless service named `prometheus-operated` for Prometheus resources, or `prometheus-agent-operated` for PrometheusAgent resources. When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each. See https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id for more details. minLength: 1 type: string sha: description: 'Deprecated: use ''spec.image'' instead. The image''s digest can be specified as part of the image name.' type: string shardRetentionPolicy: description: |- ShardRetentionPolicy defines the retention policy for the Prometheus shards. (Alpha) Using this field requires the 'PrometheusShardRetentionPolicy' feature gate to be enabled. The final goals for this feature can be seen at https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/proposals/202310-shard-autoscaling.md#graceful-scale-down-of-prometheus-servers, however, the feature is not yet fully implemented in this PR. The limitation being: * Retention duration is not settable, for now, shards are retained forever. properties: retain: description: |- Defines the config for retention when the retention policy is set to `Retain`. This field is ineffective as of now. properties: retentionPeriod: description: |- Duration is a valid time duration that can be parsed by Prometheus model.ParseDuration() function. Supported units: y, w, d, h, m, s, ms Examples: `30s`, `1m`, `1h20m15s`, `15d` 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 required: - retentionPeriod type: object whenScaled: description: |- Defines the retention policy when the Prometheus shards are scaled down. * `Delete`, the operator will delete the pods from the scaled-down shard(s). * `Retain`, the operator will keep the pods from the scaled-down shard(s), so the data can still be queried. If not defined, the operator assumes the `Delete` value. enum: - Retain - Delete type: string type: object shards: description: |- Number of shards to distribute the scraped targets onto. `spec.replicas` multiplied by `spec.shards` is the total number of Pods being created. When not defined, the operator assumes only one shard. Note that scaling down shards will not reshard data onto the remaining instances, it must be manually moved. Increasing shards will not reshard data either but it will continue to be available from the same instances. To query globally, use either * Thanos sidecar + querier for query federation and Thanos Ruler for rules. * Remote-write to send metrics to a central location. By default, the sharding of targets is performed on: * The `__address__` target's metadata label for PodMonitor, ServiceMonitor and ScrapeConfig resources. * The `__param_target__` label for Probe resources. Users can define their own sharding implementation by setting the `__tmp_hash` label during the target discovery with relabeling configuration (either in the monitoring resources or via scrape class). You can also disable sharding on a specific target by setting the `__tmp_disable_sharding` label with relabeling configuration. When the label value isn't empty, all Prometheus shards will scrape the target. format: int32 type: integer storage: description: Storage defines the storage used by Prometheus. properties: disableMountSubPath: description: 'Deprecated: subPath usage will be removed in a future release.' type: boolean emptyDir: description: |- EmptyDirVolumeSource to be used by the StatefulSet. If specified, it takes precedence over `ephemeral` and `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: 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: |- EphemeralVolumeSource to be used by the StatefulSet. This is a beta field in k8s 1.21 and GA in 1.15. For lower versions, starting with k8s 1.19, it requires enabling the GenericEphemeralVolume feature gate. More info: https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volumes 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). 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. This field is read-only and no changes will be made by Kubernetes to the PVC after it has been created. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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/volume-attributes-classes/ (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). 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 volumeClaimTemplate: description: |- Defines the PVC spec to be used by the Prometheus StatefulSets. The easiest way to use a volume that cannot be automatically provisioned is to use a label selector alongside manually created PersistentVolumes. 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: 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. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/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: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/ type: string type: object spec: description: |- 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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/volume-attributes-classes/ (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). 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: 'Deprecated: this field is never set.' 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 x-kubernetes-list-type: atomic allocatedResourceStatuses: additionalProperties: description: |- When a controller receives persistentvolume claim update with ClaimResourceStatus for a resource that it does not recognizes, then it should ignore that update and let other controllers handle it. type: string description: "allocatedResourceStatuses stores status of resource being resized for the given PVC.\nKey names follow standard Kubernetes label syntax. Valid values are either:\n\t* Un-prefixed keys:\n\t\t- storage - the capacity of the volume.\n\t* Custom resources must use implementation-defined prefixed names such as \"example.com/my-custom-resource\"\nApart from above values - keys that are unprefixed or have kubernetes.io prefix are considered\nreserved and hence may not be used.\n\nClaimResourceStatus can be in any of following states:\n\t- ControllerResizeInProgress:\n\t\tState set when resize controller starts resizing the volume in control-plane.\n\t- ControllerResizeFailed:\n\t\tState set when resize has failed in resize controller with a terminal error.\n\t- NodeResizePending:\n\t\tState set when resize controller has finished resizing the volume but further resizing of\n\t\tvolume is needed on the node.\n\t- NodeResizeInProgress:\n\t\tState set when kubelet starts resizing the volume.\n\t- NodeResizeFailed:\n\t\tState set when resizing has failed in kubelet with a terminal error. Transient errors don't set\n\t\tNodeResizeFailed.\nFor example: if expanding a PVC for more capacity - this field can be one of the following states:\n\t- pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeInProgress\"\n - pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeFailed\"\n - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizePending\"\n - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeInProgress\"\n - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeFailed\"\nWhen this field is not set, it means that no resize operation is in progress for the given PVC.\n\nA controller that receives PVC update with previously unknown resourceName or ClaimResourceStatus\nshould ignore the update for the purpose it was designed. For example - a controller that\nonly is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid\nresources associated with PVC.\n\nThis is an alpha field and requires enabling RecoverVolumeExpansionFailure feature." type: object x-kubernetes-map-type: granular 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 tracks the resources allocated to a PVC including its capacity.\nKey names follow standard Kubernetes label syntax. Valid values are either:\n\t* Un-prefixed keys:\n\t\t- storage - the capacity of the volume.\n\t* Custom resources must use implementation-defined prefixed names such as \"example.com/my-custom-resource\"\nApart from above values - keys that are unprefixed or have kubernetes.io prefix are considered\nreserved and hence may not be used.\n\nCapacity reported here may be larger than the actual capacity when a volume expansion operation\nis requested.\nFor storage quota, the larger value from allocatedResources and PVC.spec.resources is used.\nIf allocatedResources is not set, PVC.spec.resources alone is used for quota calculation.\nIf a volume expansion capacity request is lowered, allocatedResources is only\nlowered if there are no expansion operations in progress and if the actual volume capacity\nis equal or lower than the requested capacity.\n\nA controller that receives PVC update with previously unknown resourceName\nshould ignore the update for the purpose it was designed. For example - a controller that\nonly is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid\nresources associated with PVC.\n\nThis 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 'Resizing'. items: description: PersistentVolumeClaimCondition contains 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 "Resizing" that means the underlying persistent volume is being resized. type: string status: description: |- Status is the status of the condition. Can be True, False, Unknown. More info: https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/persistent-volume-claim-v1/#:~:text=state%20of%20pvc-,conditions.status,-(string)%2C%20required type: string type: description: |- Type is the type of the condition. More info: https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/persistent-volume-claim-v1/#:~:text=set%20to%20%27ResizeStarted%27.-,PersistentVolumeClaimCondition,-contains%20details%20about type: string required: - status - type type: object type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map currentVolumeAttributesClassName: description: |- currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using. When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim This is a beta field and requires enabling VolumeAttributesClass feature (off by default). type: string modifyVolumeStatus: description: |- ModifyVolumeStatus represents the status object of ControllerModifyVolume operation. When this is unset, there is no ModifyVolume operation being attempted. This is a beta field and requires enabling VolumeAttributesClass feature (off by default). properties: status: description: "status is the status of the ControllerModifyVolume operation. It can be in any of following states:\n - Pending\n Pending indicates that the PersistentVolumeClaim cannot be modified due to unmet requirements, such as\n the specified VolumeAttributesClass not existing.\n - InProgress\n InProgress indicates that the volume is being modified.\n - Infeasible\n Infeasible indicates that the request has been rejected as invalid by the CSI driver. To\n\t resolve the error, a valid VolumeAttributesClass needs to be specified.\nNote: New statuses can be added in the future. Consumers should check for unknown statuses and fail appropriately." type: string targetVolumeAttributesClassName: description: targetVolumeAttributesClassName is the name of the VolumeAttributesClass the PVC currently being reconciled type: string required: - status type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string type: object type: object type: object tag: description: 'Deprecated: use ''spec.image'' instead. The image''s tag can be specified as part of the image name.' type: string targetLimit: description: |- TargetLimit defines a limit on the number of scraped targets that will be accepted. Only valid in Prometheus versions 2.45.0 and newer. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedTargetLimit. format: int64 type: integer terminationGracePeriodSeconds: description: |- Optional duration in seconds the pod needs to terminate gracefully. Value must be non-negative integer. The value zero indicates stop immediately via the kill signal (no opportunity to shut down) which may lead to data corruption. Defaults to 600 seconds. format: int64 minimum: 0 type: integer thanos: description: Defines the configuration of the optional Thanos sidecar. properties: additionalArgs: description: |- AdditionalArgs allows setting additional arguments for the Thanos container. The arguments are passed as-is to the Thanos container which may cause issues if they are invalid or not supported the given Thanos version. In case of an argument conflict (e.g. an argument which is already set by the operator itself) or when providing an invalid argument, the reconciliation will fail and an error will be logged. items: description: Argument as part of the AdditionalArgs list. properties: name: description: Name of the argument, e.g. "scrape.discovery-reload-interval". minLength: 1 type: string value: description: Argument value, e.g. 30s. Can be empty for name-only arguments (e.g. --storage.tsdb.no-lockfile) type: string required: - name type: object type: array baseImage: description: 'Deprecated: use ''image'' instead.' type: string blockSize: default: 2h description: |- BlockDuration controls the size of TSDB blocks produced by Prometheus. The default value is 2h to match the upstream Prometheus defaults. WARNING: Changing the block duration can impact the performance and efficiency of the entire Prometheus/Thanos stack due to how it interacts with memory and Thanos compactors. It is recommended to keep this value set to a multiple of 120 times your longest scrape or rule interval. For example, 30s * 120 = 1h. 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 getConfigInterval: description: How often to retrieve the Prometheus configuration. 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 getConfigTimeout: description: Maximum time to wait when retrieving the Prometheus configuration. 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 grpcListenLocal: description: |- When true, the Thanos sidecar listens on the loopback interface instead of the Pod IP's address for the gRPC endpoints. It has no effect if `listenLocal` is true. type: boolean grpcServerTlsConfig: description: |- Configures the TLS parameters for the gRPC server providing the StoreAPI. Note: Currently only the `caFile`, `certFile`, and `keyFile` fields are supported. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object httpListenLocal: description: |- When true, the Thanos sidecar listens on the loopback interface instead of the Pod IP's address for the HTTP endpoints. It has no effect if `listenLocal` is true. type: boolean image: description: |- Container image name for Thanos. If specified, it takes precedence over the `spec.thanos.baseImage`, `spec.thanos.tag` and `spec.thanos.sha` fields. Specifying `spec.thanos.version` is still necessary to ensure the Prometheus Operator knows which version of Thanos is being configured. If neither `spec.thanos.image` nor `spec.thanos.baseImage` are defined, the operator will use the latest upstream version of Thanos available at the time when the operator was released. type: string listenLocal: description: 'Deprecated: use `grpcListenLocal` and `httpListenLocal` instead.' type: boolean logFormat: description: Log format for the Thanos sidecar. enum: - "" - logfmt - json type: string logLevel: description: Log level for the Thanos sidecar. enum: - "" - debug - info - warn - error type: string minTime: description: |- Defines the start of time range limit served by the Thanos sidecar's StoreAPI. The field's value should be a constant time in RFC3339 format or a time duration relative to current time, such as -1d or 2h45m. Valid duration units are ms, s, m, h, d, w, y. type: string objectStorageConfig: description: |- Defines the Thanos sidecar's configuration to upload TSDB blocks to object storage. More info: https://thanos.io/tip/thanos/storage.md/ objectStorageConfigFile takes precedence over this field. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic objectStorageConfigFile: description: |- Defines the Thanos sidecar's configuration file to upload TSDB blocks to object storage. More info: https://thanos.io/tip/thanos/storage.md/ This field takes precedence over objectStorageConfig. type: string readyTimeout: description: |- ReadyTimeout is the maximum time that the Thanos sidecar will wait for Prometheus to start. 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 resources: description: Defines the resources requests and limits of the Thanos sidecar. properties: claims: description: |- Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: description: |- Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. type: string request: description: |- Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object sha: description: 'Deprecated: use ''image'' instead. The image digest can be specified as part of the image name.' type: string tag: description: 'Deprecated: use ''image'' instead. The image''s tag can be specified as as part of the image name.' type: string tracingConfig: description: |- Defines the tracing configuration for the Thanos sidecar. `tracingConfigFile` takes precedence over this field. More info: https://thanos.io/tip/thanos/tracing.md/ This is an *experimental feature*, it may change in any upcoming release in a breaking way. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic tracingConfigFile: description: |- Defines the tracing configuration file for the Thanos sidecar. This field takes precedence over `tracingConfig`. More info: https://thanos.io/tip/thanos/tracing.md/ This is an *experimental feature*, it may change in any upcoming release in a breaking way. type: string version: description: |- Version of Thanos being deployed. The operator uses this information to generate the Prometheus StatefulSet + configuration files. If not specified, the operator assumes the latest upstream release of Thanos available at the time when the version of the operator was released. type: string volumeMounts: description: |- VolumeMounts allows configuration of additional VolumeMounts for Thanos. VolumeMounts specified will be appended to other VolumeMounts in the 'thanos-sidecar' container. 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. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None). 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 recursiveReadOnly: description: |- RecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled. type: string 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 tolerations: description: Defines the Pods' tolerations if specified. 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: Defines the pod's topology spread constraints if specified. items: properties: additionalLabelSelectors: description: Defines what Prometheus Operator managed labels should be added to labelSelector on the topologySpreadConstraint. enum: - OnResource - OnShard type: string labelSelector: description: |- LabelSelector is used to find matching pods. Pods that match this label selector are counted to determine the number of pods in their corresponding topology domain. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. MatchLabelKeys cannot be set when LabelSelector isn't set. Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. 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. 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. format: int32 type: integer nodeAffinityPolicy: description: |- NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. type: string nodeTaintsPolicy: description: |- NodeTaintsPolicy indicates how we will treat node taints when calculating pod topology spread skew. Options are: - Honor: nodes without taints, along with tainted nodes for which the incoming pod has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. 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 tracingConfig: description: |- TracingConfig configures tracing in Prometheus. This is an *experimental feature*, it may change in any upcoming release in a breaking way. properties: clientType: description: Client used to export the traces. Supported values are `http` or `grpc`. enum: - http - grpc type: string compression: description: Compression key for supported compression types. The only supported value is `gzip`. enum: - gzip type: string endpoint: description: Endpoint to send the traces to. Should be provided in format :. minLength: 1 type: string headers: additionalProperties: type: string description: Key-value pairs to be used as headers associated with gRPC or HTTP requests. type: object insecure: description: If disabled, the client will use a secure connection. type: boolean samplingFraction: anyOf: - type: integer - type: string description: Sets the probability a given trace will be sampled. Must be a float from 0 through 1. pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true timeout: description: Maximum time the exporter will wait for each batch export. 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 tlsConfig: description: TLS Config to use when sending traces. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - endpoint type: object tsdb: description: |- Defines the runtime reloadable configuration of the timeseries database(TSDB). It requires Prometheus >= v2.39.0 or PrometheusAgent >= v2.54.0. properties: outOfOrderTimeWindow: description: |- Configures how old an out-of-order/out-of-bounds sample can be with respect to the TSDB max time. An out-of-order/out-of-bounds sample is ingested into the TSDB as long as the timestamp of the sample is >= (TSDB.MaxTime - outOfOrderTimeWindow). This is an *experimental feature*, it may change in any upcoming release in a breaking way. It requires Prometheus >= v2.39.0 or PrometheusAgent >= v2.54.0. 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 type: object version: description: |- Version of Prometheus being deployed. The operator uses this information to generate the Prometheus StatefulSet + configuration files. If not specified, the operator assumes the latest upstream version of Prometheus available at the time when the version of the operator was released. type: string volumeMounts: description: |- VolumeMounts allows the configuration of additional VolumeMounts. VolumeMounts will be appended to other VolumeMounts in the 'prometheus' 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. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None). 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 recursiveReadOnly: description: |- RecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled. type: string 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 the 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. properties: awsElasticBlockStore: description: |- awsElasticBlockStore represents an AWS Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Deprecated: AWSElasticBlockStore is deprecated. All operations for the in-tree awsElasticBlockStore type are redirected to the ebs.csi.aws.com CSI driver. 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 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. Deprecated: AzureDisk is deprecated. All operations for the in-tree azureDisk type are redirected to the disk.csi.azure.com CSI driver. 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: default: ext4 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: default: false 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. Deprecated: AzureFile is deprecated. All operations for the in-tree azureFile type are redirected to the file.csi.azure.com CSI driver. 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. Deprecated: CephFS is deprecated and the in-tree cephfs type is no longer supported. 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: Cinder is deprecated. All operations for the in-tree cinder type are redirected to the cinder.csi.openstack.org CSI driver. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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 x-kubernetes-list-type: atomic name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: 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. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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, namespace and uid 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 x-kubernetes-list-type: atomic 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. 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). Use PersistentVolumeClaim or one of the vendor-specific APIs for volumes that persist for longer than the lifecycle of an individual pod. 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. 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). 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. This field is read-only and no changes will be made by Kubernetes to the PVC after it has been created. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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/volume-attributes-classes/ (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). 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. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic type: object flexVolume: description: |- flexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. Deprecated: FlexVolume is deprecated. Consider using a CSIDriver instead. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: Flocker is deprecated and the in-tree flocker type is no longer supported. 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. Deprecated: GCEPersistentDisk is deprecated. All operations for the in-tree gcePersistentDisk type are redirected to the pd.csi.storage.gke.io CSI driver. 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 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. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported. 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 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 image: description: |- image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided: - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. The volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro) and non-executable files (noexec). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: pullPolicy: description: |- Policy for pulling OCI objects. Possible values are: Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. type: string reference: description: |- Required: Image or artifact reference to be used. Behaves in the same way as pod.spec.containers[*].image. Pull secrets will be assembled in the same way as for the container image by looking up node credentials, SA image pull secrets, and pod spec image pull secrets. 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 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 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: default: default 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: PhotonPersistentDisk is deprecated and the in-tree photonPersistentDisk type is no longer supported. 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. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on. 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. Each entry in this list handles one source. items: description: |- Projection that may be projected along with other supported volume types. Exactly one of these fields must be set. properties: clusterTrustBundle: description: |- ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. Alpha, gated by the ClusterTrustBundleProjection feature gate. ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: 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, namespace and uid 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: 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 x-kubernetes-list-type: atomic type: object quobyte: description: |- quobyte represents a Quobyte mount on the host that shares a pod's lifetime. Deprecated: Quobyte is deprecated and the in-tree quobyte type is no longer supported. 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. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. 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 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: default: /etc/ceph/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 x-kubernetes-list-type: atomic pool: default: rbd 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string type: object x-kubernetes-map-type: atomic user: default: admin 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. Deprecated: ScaleIO is deprecated and the in-tree scaleIO type is no longer supported. properties: fsType: default: xfs 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string type: object x-kubernetes-map-type: atomic sslEnabled: description: sslEnabled Flag enable/disable SSL communication with Gateway, default false type: boolean storageMode: default: ThinProvisioned 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 x-kubernetes-list-type: atomic 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. Deprecated: StorageOS is deprecated and the in-tree storageos type is no longer supported. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: VsphereVolume is deprecated. All operations for the in-tree vsphereVolume type are redirected to the csi.vsphere.vmware.com CSI driver. 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 walCompression: description: |- Configures compression of the write-ahead log (WAL) using Snappy. WAL compression is enabled by default for Prometheus >= 2.20.0 Requires Prometheus v2.11.0 and above. type: boolean web: description: Defines the configuration of the Prometheus web server. properties: httpConfig: description: Defines HTTP parameters for web server. properties: headers: description: List of headers that can be added to HTTP responses. properties: contentSecurityPolicy: description: |- Set the Content-Security-Policy header to HTTP responses. Unset if blank. type: string strictTransportSecurity: description: |- Set the Strict-Transport-Security header to HTTP responses. Unset if blank. Please make sure that you use this with care as this header might force browsers to load Prometheus and the other applications hosted on the same domain and subdomains over HTTPS. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security type: string xContentTypeOptions: description: |- Set the X-Content-Type-Options header to HTTP responses. Unset if blank. Accepted value is nosniff. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options enum: - "" - NoSniff type: string xFrameOptions: description: |- Set the X-Frame-Options header to HTTP responses. Unset if blank. Accepted values are deny and sameorigin. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options enum: - "" - Deny - SameOrigin type: string xXSSProtection: description: |- Set the X-XSS-Protection header to all responses. Unset if blank. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection type: string type: object http2: description: |- Enable HTTP/2 support. Note that HTTP/2 is only supported with TLS. When TLSConfig is not configured, HTTP/2 will be disabled. Whenever the value of the field changes, a rolling update will be triggered. type: boolean type: object maxConnections: description: |- Defines the maximum number of simultaneous connections A zero value means that Prometheus doesn't accept any incoming connection. format: int32 minimum: 0 type: integer pageTitle: description: The prometheus web page title. type: string tlsConfig: description: Defines the TLS parameters for HTTPS. properties: cert: description: |- Secret or ConfigMap containing the TLS certificate for the web server. Either `keySecret` or `keyFile` must be defined. It is mutually exclusive with `certFile`. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object certFile: description: |- Path to the TLS certificate file in the container for the web server. Either `keySecret` or `keyFile` must be defined. It is mutually exclusive with `cert`. type: string cipherSuites: description: |- List of supported cipher suites for TLS versions up to TLS 1.2. If not defined, the Go default cipher suites are used. Available cipher suites are documented in the Go documentation: https://golang.org/pkg/crypto/tls/#pkg-constants items: type: string type: array client_ca: description: |- Secret or ConfigMap containing the CA certificate for client certificate authentication to the server. It is mutually exclusive with `clientCAFile`. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientAuthType: description: |- The server policy for client TLS authentication. For more detail on clientAuth options: https://golang.org/pkg/crypto/tls/#ClientAuthType type: string clientCAFile: description: |- Path to the CA certificate file for client certificate authentication to the server. It is mutually exclusive with `client_ca`. type: string curvePreferences: description: |- Elliptic curves that will be used in an ECDHE handshake, in preference order. Available curves are documented in the Go documentation: https://golang.org/pkg/crypto/tls/#CurveID items: type: string type: array keyFile: description: |- Path to the TLS private key file in the container for the web server. If defined, either `cert` or `certFile` must be defined. It is mutually exclusive with `keySecret`. type: string keySecret: description: |- Secret containing the TLS private key for the web server. Either `cert` or `certFile` must be defined. It is mutually exclusive with `keyFile`. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: Maximum TLS version that is acceptable. type: string minVersion: description: Minimum TLS version that is acceptable. type: string preferServerCipherSuites: description: |- Controls whether the server selects the client's most preferred cipher suite, or the server's most preferred cipher suite. If true then the server's preference, as expressed in the order of elements in cipherSuites, is used. type: boolean type: object type: object type: object status: description: |- Most recent observed status of the Prometheus cluster. Read-only. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status properties: availableReplicas: description: |- Total number of available pods (ready for at least minReadySeconds) targeted by this Prometheus deployment. format: int32 type: integer conditions: description: The current state of the Prometheus deployment. items: description: |- Condition represents the state of the resources associated with the Prometheus, Alertmanager or ThanosRuler resource. properties: lastTransitionTime: description: lastTransitionTime is the time of the last update to the current status property. format: date-time type: string message: description: Human-readable message indicating details for the condition's last transition. 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[].observedGeneration` is 9, the condition is out of date with respect to the current state of the instance. format: int64 type: integer reason: description: Reason for the condition's last transition. type: string status: description: Status of the condition. minLength: 1 type: string type: description: Type of the condition being reported. minLength: 1 type: string required: - lastTransitionTime - status - type type: object type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map paused: description: |- Represents whether any actions on the underlying managed objects are being performed. Only delete actions will be performed. type: boolean replicas: description: |- Total number of non-terminated pods targeted by this Prometheus deployment (their labels match the selector). format: int32 type: integer selector: description: The selector used to match the pods targeted by this Prometheus resource. type: string shardStatuses: description: The list has one entry per shard. Each entry provides a summary of the shard status. items: properties: availableReplicas: description: |- Total number of available pods (ready for at least minReadySeconds) targeted by this shard. format: int32 type: integer replicas: description: Total number of pods targeted by this shard. format: int32 type: integer shardID: description: Identifier of the shard. type: string unavailableReplicas: description: Total number of unavailable pods targeted by this shard. format: int32 type: integer updatedReplicas: description: |- Total number of non-terminated pods targeted by this shard that have the desired spec. format: int32 type: integer required: - availableReplicas - replicas - shardID - unavailableReplicas - updatedReplicas type: object type: array x-kubernetes-list-map-keys: - shardID x-kubernetes-list-type: map shards: description: Shards is the most recently observed number of shards. format: int32 type: integer unavailableReplicas: description: Total number of unavailable pods targeted by this Prometheus deployment. format: int32 type: integer updatedReplicas: description: |- Total number of non-terminated pods targeted by this Prometheus deployment 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: scale: labelSelectorPath: .status.selector specReplicasPath: .spec.shards statusReplicasPath: .status.shards status: {} ================================================ FILE: hack/config/monitoring/crds/0prometheusagentCustomResourceDefinition.yaml ================================================ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 operator.prometheus.io/version: 0.85.0 name: prometheusagents.monitoring.coreos.com spec: group: monitoring.coreos.com names: categories: - prometheus-operator kind: PrometheusAgent listKind: PrometheusAgentList plural: prometheusagents shortNames: - promagent singular: prometheusagent scope: Namespaced versions: - additionalPrinterColumns: - description: The version of Prometheus agent jsonPath: .spec.version name: Version type: string - description: The number of desired replicas jsonPath: .spec.replicas name: Desired type: integer - description: The number of ready replicas jsonPath: .status.availableReplicas name: Ready type: integer - jsonPath: .status.conditions[?(@.type == 'Reconciled')].status name: Reconciled type: string - jsonPath: .status.conditions[?(@.type == 'Available')].status name: Available type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - description: Whether the resource reconciliation is paused or not jsonPath: .status.paused name: Paused priority: 1 type: boolean name: v1alpha1 schema: openAPIV3Schema: description: |- The `PrometheusAgent` custom resource definition (CRD) defines a desired [Prometheus Agent](https://prometheus.io/blog/2021/11/16/agent/) setup to run in a Kubernetes cluster. The CRD is very similar to the `Prometheus` CRD except for features which aren't available in agent mode like rule evaluation, persistent storage and Thanos sidecar. 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 Prometheus agent. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status properties: additionalArgs: description: |- AdditionalArgs allows setting additional arguments for the 'prometheus' container. It is intended for e.g. activating hidden flags which are not supported by the dedicated configuration options yet. The arguments are passed as-is to the Prometheus container which may cause issues if they are invalid or not supported by the given Prometheus version. In case of an argument conflict (e.g. an argument which is already set by the operator itself) or when providing an invalid argument, the reconciliation will fail and an error will be logged. items: description: Argument as part of the AdditionalArgs list. properties: name: description: Name of the argument, e.g. "scrape.discovery-reload-interval". minLength: 1 type: string value: description: Argument value, e.g. 30s. Can be empty for name-only arguments (e.g. --storage.tsdb.no-lockfile) type: string required: - name type: object type: array additionalScrapeConfigs: description: |- AdditionalScrapeConfigs allows specifying a key of a Secret containing additional Prometheus scrape configurations. Scrape configurations specified are appended to the configurations generated by the Prometheus Operator. Job configurations specified must have the form as specified in the official Prometheus documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config. 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 Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible scrape configs are going to break Prometheus after the upgrade. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic affinity: description: Defines the Pods' affinity scheduling rules if specified. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic type: object type: object apiserverConfig: description: |- APIServerConfig allows specifying a host and auth methods to access the Kuberntees API server. If null, Prometheus is assumed to run inside of the cluster: it will discover the 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 section for the API server. Cannot be set at the same time as `basicAuth`, `bearerToken`, or `bearerTokenFile`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic credentialsFile: description: File to read a secret from, mutually exclusive with `credentials`. type: string type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth configuration for the API server. Cannot be set at the same time as `authorization`, `bearerToken`, or `bearerTokenFile`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerToken: description: |- *Warning: this field shouldn't be used because the token value appears in clear-text. Prefer using `authorization`.* Deprecated: this will be removed in a future release. type: string bearerTokenFile: description: |- File to read bearer token for accessing apiserver. Cannot be set at the same time as `basicAuth`, `authorization`, or `bearerToken`. Deprecated: this will be removed in a future release. Prefer using `authorization`. type: string host: description: |- Kubernetes API address consisting of a hostname or IP address followed by an optional port number. type: string noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string tlsConfig: description: TLS Config to use for the API server. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - host type: object arbitraryFSAccessThroughSMs: description: |- When true, ServiceMonitor, PodMonitor and Probe object are forbidden to reference arbitrary files on the file system of the 'prometheus' container. When a ServiceMonitor's endpoint specifies a `bearerTokenFile` value (e.g. '/var/run/secrets/kubernetes.io/serviceaccount/token'), a malicious target can get access to the Prometheus service account's token in the Prometheus' scrape request. Setting `spec.arbitraryFSAccessThroughSM` to 'true' would prevent the attack. Users should instead provide the credentials using the `spec.bearerTokenSecret` field. properties: deny: type: boolean type: object automountServiceAccountToken: description: |- AutomountServiceAccountToken indicates whether a service account token should be automatically mounted in the pod. If the field isn't set, the operator mounts the service account token by default. **Warning:** be aware that by default, Prometheus requires the service account token for Kubernetes service discovery. It is possible to use strategic merge patch to project the service account token into the 'prometheus' container. type: boolean bodySizeLimit: description: |- BodySizeLimit defines per-scrape on response body size. Only valid in Prometheus versions 2.45.0 and newer. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedBodySizeLimit. pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$ type: string configMaps: description: |- ConfigMaps is a list of ConfigMaps in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. Each ConfigMap is added to the StatefulSet definition as a volume named `configmap-`. The ConfigMaps are mounted into /etc/prometheus/configmaps/ in the 'prometheus' container. items: type: string type: array containers: description: |- Containers allows injecting additional containers or modifying operator generated containers. This can be used to allow adding an authentication proxy to the Pods or to change the behavior of an operator generated container. Containers described here modify an operator generated container if they share the same name and modifications are done via a strategic merge patch. The names of containers managed by the operator are: * `prometheus` * `config-reloader` * `thanos-sidecar` Overriding containers 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. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: description: |- Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string description: Specifies the output format of the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: description: Selects a key of a secret in the pod's namespace properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map 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 or Secrets properties: configMapRef: description: The ConfigMap to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret must be defined type: boolean type: object x-kubernetes-map-type: atomic type: object type: array x-kubernetes-list-type: atomic 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 stopSignal: description: |- StopSignal defines which signal will be sent to a container when it is being stopped. If not specified, the default is defined by the container runtime in use. StopSignal can only be set for Pods with a non-empty .spec.os.name type: string 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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. This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: description: |- Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. type: string request: description: |- Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object 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 appArmorProfile: description: |- appArmorProfile is the AppArmor options to use by this container. If set, this profile overrides the pod's appArmorProfile. Note that this field cannot be set when spec.os.name is windows. properties: localhostProfile: description: |- localhostProfile indicates a profile loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost". type: string type: description: |- type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement. type: string required: - type type: object 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 x-kubernetes-list-type: atomic drop: description: Removed capabilities items: description: Capability represent POSIX capabilities type type: string type: array x-kubernetes-list-type: atomic 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 value is Default 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: 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 x-kubernetes-list-map-keys: - devicePath x-kubernetes-list-type: map 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. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None). 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 recursiveReadOnly: description: |- RecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled. type: string 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 x-kubernetes-list-map-keys: - mountPath x-kubernetes-list-type: map 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 convertClassicHistogramsToNHCB: description: |- Whether to convert all scraped classic histograms into a native histogram with custom buckets. It requires Prometheus >= v3.4.0. type: boolean dnsConfig: description: Defines the DNS configuration for the pods. properties: nameservers: description: |- A list of DNS name server IP addresses. This will be appended to the base nameservers generated from DNSPolicy. items: minLength: 1 type: string type: array x-kubernetes-list-type: set options: description: |- A list of DNS resolver options. This will be merged with the base options generated from DNSPolicy. 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: Name is required and must be unique. minLength: 1 type: string value: description: Value is optional. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map searches: description: |- A list of DNS search domains for host-name lookup. This will be appended to the base search paths generated from DNSPolicy. items: minLength: 1 type: string type: array x-kubernetes-list-type: set type: object dnsPolicy: description: Defines the DNS policy for the pods. enum: - ClusterFirstWithHostNet - ClusterFirst - Default - None type: string enableFeatures: description: |- Enable access to Prometheus feature flags. By default, no features are enabled. Enabling features which are disabled by default 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. For more information see https://prometheus.io/docs/prometheus/latest/feature_flags/ items: minLength: 1 type: string type: array x-kubernetes-list-type: set enableOTLPReceiver: description: |- Enable Prometheus to be used as a receiver for the OTLP Metrics protocol. Note that the OTLP receiver endpoint is automatically enabled if `.spec.otlpConfig` is defined. It requires Prometheus >= v2.47.0. type: boolean enableRemoteWriteReceiver: description: |- Enable Prometheus to be used as a receiver for the Prometheus remote write protocol. WARNING: This is not considered an efficient way of ingesting samples. Use it with caution for specific low-volume use cases. It is not suitable for replacing the ingestion via scraping and turning Prometheus into a push-based metrics collection system. For more information see https://prometheus.io/docs/prometheus/latest/querying/api/#remote-write-receiver It requires Prometheus >= v2.33.0. type: boolean enableServiceLinks: description: Indicates whether information about services should be injected into pod's environment variables type: boolean enforcedBodySizeLimit: description: |- When defined, enforcedBodySizeLimit specifies a global limit on the size of uncompressed response body that will be accepted by Prometheus. Targets responding with a body larger than this many bytes will cause the scrape to fail. It requires Prometheus >= v2.28.0. When both `enforcedBodySizeLimit` and `bodySizeLimit` are defined and greater than zero, the following rules apply: * Scrape objects without a defined bodySizeLimit value will inherit the global bodySizeLimit value (Prometheus >= 2.45.0) or the enforcedBodySizeLimit value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedBodySizeLimit` is greater than the `bodySizeLimit`, the `bodySizeLimit` will be set to `enforcedBodySizeLimit`. * Scrape objects with a bodySizeLimit value less than or equal to enforcedBodySizeLimit keep their specific value. * Scrape objects with a bodySizeLimit value greater than enforcedBodySizeLimit are set to enforcedBodySizeLimit. pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$ type: string enforcedKeepDroppedTargets: description: |- When defined, enforcedKeepDroppedTargets specifies a global limit on the number of targets dropped by relabeling that will be kept in memory. The value overrides any `spec.keepDroppedTargets` set by ServiceMonitor, PodMonitor, Probe objects unless `spec.keepDroppedTargets` is greater than zero and less than `spec.enforcedKeepDroppedTargets`. It requires Prometheus >= v2.47.0. When both `enforcedKeepDroppedTargets` and `keepDroppedTargets` are defined and greater than zero, the following rules apply: * Scrape objects without a defined keepDroppedTargets value will inherit the global keepDroppedTargets value (Prometheus >= 2.45.0) or the enforcedKeepDroppedTargets value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedKeepDroppedTargets` is greater than the `keepDroppedTargets`, the `keepDroppedTargets` will be set to `enforcedKeepDroppedTargets`. * Scrape objects with a keepDroppedTargets value less than or equal to enforcedKeepDroppedTargets keep their specific value. * Scrape objects with a keepDroppedTargets value greater than enforcedKeepDroppedTargets are set to enforcedKeepDroppedTargets. format: int64 type: integer enforcedLabelLimit: description: |- When defined, enforcedLabelLimit specifies a global limit on the number of labels per sample. The value overrides any `spec.labelLimit` set by ServiceMonitor, PodMonitor, Probe objects unless `spec.labelLimit` is greater than zero and less than `spec.enforcedLabelLimit`. It requires Prometheus >= v2.27.0. When both `enforcedLabelLimit` and `labelLimit` are defined and greater than zero, the following rules apply: * Scrape objects without a defined labelLimit value will inherit the global labelLimit value (Prometheus >= 2.45.0) or the enforcedLabelLimit value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedLabelLimit` is greater than the `labelLimit`, the `labelLimit` will be set to `enforcedLabelLimit`. * Scrape objects with a labelLimit value less than or equal to enforcedLabelLimit keep their specific value. * Scrape objects with a labelLimit value greater than enforcedLabelLimit are set to enforcedLabelLimit. format: int64 type: integer enforcedLabelNameLengthLimit: description: |- When defined, enforcedLabelNameLengthLimit specifies a global limit on the length of labels name per sample. The value overrides any `spec.labelNameLengthLimit` set by ServiceMonitor, PodMonitor, Probe objects unless `spec.labelNameLengthLimit` is greater than zero and less than `spec.enforcedLabelNameLengthLimit`. It requires Prometheus >= v2.27.0. When both `enforcedLabelNameLengthLimit` and `labelNameLengthLimit` are defined and greater than zero, the following rules apply: * Scrape objects without a defined labelNameLengthLimit value will inherit the global labelNameLengthLimit value (Prometheus >= 2.45.0) or the enforcedLabelNameLengthLimit value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedLabelNameLengthLimit` is greater than the `labelNameLengthLimit`, the `labelNameLengthLimit` will be set to `enforcedLabelNameLengthLimit`. * Scrape objects with a labelNameLengthLimit value less than or equal to enforcedLabelNameLengthLimit keep their specific value. * Scrape objects with a labelNameLengthLimit value greater than enforcedLabelNameLengthLimit are set to enforcedLabelNameLengthLimit. format: int64 type: integer enforcedLabelValueLengthLimit: description: |- When not null, enforcedLabelValueLengthLimit defines a global limit on the length of labels value per sample. The value overrides any `spec.labelValueLengthLimit` set by ServiceMonitor, PodMonitor, Probe objects unless `spec.labelValueLengthLimit` is greater than zero and less than `spec.enforcedLabelValueLengthLimit`. It requires Prometheus >= v2.27.0. When both `enforcedLabelValueLengthLimit` and `labelValueLengthLimit` are defined and greater than zero, the following rules apply: * Scrape objects without a defined labelValueLengthLimit value will inherit the global labelValueLengthLimit value (Prometheus >= 2.45.0) or the enforcedLabelValueLengthLimit value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedLabelValueLengthLimit` is greater than the `labelValueLengthLimit`, the `labelValueLengthLimit` will be set to `enforcedLabelValueLengthLimit`. * Scrape objects with a labelValueLengthLimit value less than or equal to enforcedLabelValueLengthLimit keep their specific value. * Scrape objects with a labelValueLengthLimit value greater than enforcedLabelValueLengthLimit are set to enforcedLabelValueLengthLimit. format: int64 type: integer enforcedNamespaceLabel: description: |- When not empty, a label will be added to: 1. All metrics scraped from `ServiceMonitor`, `PodMonitor`, `Probe` and `ScrapeConfig` objects. 2. All metrics generated from recording rules defined in `PrometheusRule` objects. 3. All alerts generated from alerting rules defined in `PrometheusRule` objects. 4. All vector selectors of PromQL expressions defined in `PrometheusRule` objects. The label will not added for objects referenced in `spec.excludedFromEnforcement`. The label's name is this field's value. The label's value is the namespace of the `ServiceMonitor`, `PodMonitor`, `Probe`, `PrometheusRule` or `ScrapeConfig` object. type: string enforcedSampleLimit: description: |- When defined, enforcedSampleLimit specifies a global limit on the number of scraped samples that will be accepted. This overrides any `spec.sampleLimit` set by ServiceMonitor, PodMonitor, Probe objects unless `spec.sampleLimit` is greater than zero and less than `spec.enforcedSampleLimit`. It is meant to be used by admins to keep the overall number of samples/series under a desired limit. When both `enforcedSampleLimit` and `sampleLimit` are defined and greater than zero, the following rules apply: * Scrape objects without a defined sampleLimit value will inherit the global sampleLimit value (Prometheus >= 2.45.0) or the enforcedSampleLimit value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedSampleLimit` is greater than the `sampleLimit`, the `sampleLimit` will be set to `enforcedSampleLimit`. * Scrape objects with a sampleLimit value less than or equal to enforcedSampleLimit keep their specific value. * Scrape objects with a sampleLimit value greater than enforcedSampleLimit are set to enforcedSampleLimit. format: int64 type: integer enforcedTargetLimit: description: |- When defined, enforcedTargetLimit specifies a global limit on the number of scraped targets. The value overrides any `spec.targetLimit` set by ServiceMonitor, PodMonitor, Probe objects unless `spec.targetLimit` is greater than zero and less than `spec.enforcedTargetLimit`. It is meant to be used by admins to to keep the overall number of targets under a desired limit. When both `enforcedTargetLimit` and `targetLimit` are defined and greater than zero, the following rules apply: * Scrape objects without a defined targetLimit value will inherit the global targetLimit value (Prometheus >= 2.45.0) or the enforcedTargetLimit value (Prometheus < v2.45.0). If Prometheus version is >= 2.45.0 and the `enforcedTargetLimit` is greater than the `targetLimit`, the `targetLimit` will be set to `enforcedTargetLimit`. * Scrape objects with a targetLimit value less than or equal to enforcedTargetLimit keep their specific value. * Scrape objects with a targetLimit value greater than enforcedTargetLimit are set to enforcedTargetLimit. format: int64 type: integer excludedFromEnforcement: description: |- List of references to PodMonitor, ServiceMonitor, Probe and PrometheusRule objects to be excluded from enforcing a namespace label of origin. It is only applicable if `spec.enforcedNamespaceLabel` set to true. items: description: ObjectReference references a PodMonitor, ServiceMonitor, Probe or PrometheusRule object. properties: group: default: monitoring.coreos.com description: Group of the referent. When not specified, it defaults to `monitoring.coreos.com` enum: - monitoring.coreos.com type: string name: description: Name of the referent. When not set, all resources in the namespace are matched. type: string namespace: description: |- Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ minLength: 1 type: string resource: description: Resource of the referent. enum: - prometheusrules - servicemonitors - podmonitors - probes - scrapeconfigs type: string required: - namespace - resource type: object type: array externalLabels: additionalProperties: type: string description: |- The labels to add to any time series or alerts when communicating with external systems (federation, remote storage, Alertmanager). Labels defined by `spec.replicaExternalLabelName` and `spec.prometheusExternalLabelName` take precedence over this list. type: object externalUrl: description: |- The external URL under which the Prometheus service is externally available. This is necessary to generate correct URLs (for instance if Prometheus is accessible behind an Ingress resource). type: string hostAliases: description: |- Optional list of hosts and IPs that will be injected into the Pod's hosts file if specified. 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 required: - hostnames - ip type: object type: array x-kubernetes-list-map-keys: - ip x-kubernetes-list-type: map hostNetwork: description: |- Use the host's network namespace if true. Make sure to understand the security implications if you want to enable it (https://kubernetes.io/docs/concepts/configuration/overview/ ). When hostNetwork is enabled, this will set the DNS policy to `ClusterFirstWithHostNet` automatically (unless `.spec.DNSPolicy` is set to a different value). type: boolean hostUsers: description: |- HostUsers supports the user space in Kubernetes. More info: https://kubernetes.io/docs/tasks/configure-pod-container/user-namespaces/ The feature requires at least Kubernetes 1.28 with the `UserNamespacesSupport` feature gate enabled. Starting Kubernetes 1.33, the feature is enabled by default. type: boolean ignoreNamespaceSelectors: description: |- When true, `spec.namespaceSelector` from all PodMonitor, ServiceMonitor and Probe objects will be ignored. They will only discover targets within the namespace of the PodMonitor, ServiceMonitor and Probe object. type: boolean image: description: |- Container image name for Prometheus. If specified, it takes precedence over the `spec.baseImage`, `spec.tag` and `spec.sha` fields. Specifying `spec.version` is still necessary to ensure the Prometheus Operator knows which version of Prometheus is being configured. If neither `spec.image` nor `spec.baseImage` are defined, the operator will use the latest upstream version of Prometheus available at the time when the operator was released. type: string imagePullPolicy: description: |- Image pull policy for the 'prometheus', 'init-config-reloader' and 'config-reloader' containers. See https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy for more details. enum: - "" - Always - Never - IfNotPresent type: string imagePullSecrets: description: |- An optional list of references to Secrets in the same namespace to use for pulling images from registries. See http://kubernetes.io/docs/user-guide/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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string type: object x-kubernetes-map-type: atomic type: array initContainers: description: |- InitContainers allows injecting initContainers to the Pod definition. Those can be used to e.g. fetch secrets for injection into the Prometheus 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/ InitContainers described here modify an operator generated init containers if they share the same name and modifications are done via a strategic merge patch. The names of init container name managed by the operator are: * `init-config-reloader`. Overriding init containers 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. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: description: |- Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string description: Specifies the output format of the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: description: Selects a key of a secret in the pod's namespace properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map 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 or Secrets properties: configMapRef: description: The ConfigMap to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret must be defined type: boolean type: object x-kubernetes-map-type: atomic type: object type: array x-kubernetes-list-type: atomic 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 stopSignal: description: |- StopSignal defines which signal will be sent to a container when it is being stopped. If not specified, the default is defined by the container runtime in use. StopSignal can only be set for Pods with a non-empty .spec.os.name type: string 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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. This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: description: |- Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. type: string request: description: |- Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object 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 appArmorProfile: description: |- appArmorProfile is the AppArmor options to use by this container. If set, this profile overrides the pod's appArmorProfile. Note that this field cannot be set when spec.os.name is windows. properties: localhostProfile: description: |- localhostProfile indicates a profile loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost". type: string type: description: |- type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement. type: string required: - type type: object 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 x-kubernetes-list-type: atomic drop: description: Removed capabilities items: description: Capability represent POSIX capabilities type type: string type: array x-kubernetes-list-type: atomic 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 value is Default 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: 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 x-kubernetes-list-map-keys: - devicePath x-kubernetes-list-type: map 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. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None). 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 recursiveReadOnly: description: |- RecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled. type: string 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 x-kubernetes-list-map-keys: - mountPath x-kubernetes-list-type: map 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 keepDroppedTargets: description: |- Per-scrape limit on the number of targets dropped by relabeling that will be kept in memory. 0 means no limit. It requires Prometheus >= v2.47.0. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedKeepDroppedTargets. format: int64 type: integer labelLimit: description: |- Per-scrape limit on number of labels that will be accepted for a sample. Only valid in Prometheus versions 2.45.0 and newer. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedLabelLimit. 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.45.0 and newer. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedLabelNameLengthLimit. 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.45.0 and newer. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedLabelValueLengthLimit. format: int64 type: integer listenLocal: description: |- When true, the Prometheus server listens on the loopback address instead of the Pod IP's address. type: boolean logFormat: description: Log format for Log level for Prometheus and the config-reloader sidecar. enum: - "" - logfmt - json type: string logLevel: description: Log level for Prometheus and the config-reloader sidecar. enum: - "" - debug - info - warn - error type: string maximumStartupDurationSeconds: description: |- Defines the maximum time that the `prometheus` container's startup probe will wait before being considered failed. The startup probe will return success after the WAL replay is complete. If set, the value should be greater than 60 (seconds). Otherwise it will be equal to 600 seconds (15 minutes). format: int32 minimum: 60 type: integer minReadySeconds: description: |- Minimum number of seconds for which a newly created Pod should be ready without any of its container crashing for it to be considered available. If unset, pods will be considered available as soon as they are ready. format: int32 minimum: 0 type: integer mode: description: |- Mode defines how the Prometheus operator deploys the PrometheusAgent pod(s). (Alpha) Using this field requires the `PrometheusAgentDaemonSet` feature gate to be enabled. enum: - StatefulSet - DaemonSet type: string nameEscapingScheme: description: |- Specifies the character escaping scheme that will be requested when scraping for metric and label names that do not conform to the legacy Prometheus character set. It requires Prometheus >= v3.4.0. enum: - AllowUTF8 - Underscores - Dots - Values type: string nameValidationScheme: description: |- Specifies the validation scheme for metric and label names. It requires Prometheus >= v2.55.0. enum: - UTF8 - Legacy type: string nodeSelector: additionalProperties: type: string description: Defines on which Nodes the Pods are scheduled. type: object otlp: description: |- Settings related to the OTLP receiver feature. It requires Prometheus >= v2.55.0. properties: convertHistogramsToNHCB: description: |- Configures optional translation of OTLP explicit bucket histograms into native histograms with custom buckets. It requires Prometheus >= v3.4.0. type: boolean ignoreResourceAttributes: description: |- List of OpenTelemetry resource attributes to ignore when `promoteAllResourceAttributes` is true. It requires `promoteAllResourceAttributes` to be true. It requires Prometheus >= v3.5.0. items: minLength: 1 type: string minItems: 1 type: array x-kubernetes-list-type: set keepIdentifyingResourceAttributes: description: |- Enables adding `service.name`, `service.namespace` and `service.instance.id` resource attributes to the `target_info` metric, on top of converting them into the `instance` and `job` labels. It requires Prometheus >= v3.1.0. type: boolean promoteAllResourceAttributes: description: |- Promote all resource attributes to metric labels except the ones defined in `ignoreResourceAttributes`. Cannot be true when `promoteResourceAttributes` is defined. It requires Prometheus >= v3.5.0. type: boolean promoteResourceAttributes: description: |- List of OpenTelemetry Attributes that should be promoted to metric labels, defaults to none. Cannot be defined when `promoteAllResourceAttributes` is true. items: minLength: 1 type: string minItems: 1 type: array x-kubernetes-list-type: set translationStrategy: description: |- Configures how the OTLP receiver endpoint translates the incoming metrics. It requires Prometheus >= v3.0.0. enum: - NoUTF8EscapingWithSuffixes - UnderscoreEscapingWithSuffixes - NoTranslation type: string type: object overrideHonorLabels: description: |- When true, Prometheus resolves label conflicts by renaming the labels in the scraped data to “exported_” for all targets created from ServiceMonitor, PodMonitor and ScrapeConfig objects. Otherwise the HonorLabels field of the service or pod monitor applies. In practice,`overrideHonorLaels:true` enforces `honorLabels:false` for all ServiceMonitor, PodMonitor and ScrapeConfig objects. type: boolean overrideHonorTimestamps: description: |- When true, Prometheus ignores the timestamps for all the targets created from service and pod monitors. Otherwise the HonorTimestamps field of the service or pod monitor applies. type: boolean paused: description: |- When a Prometheus deployment is paused, no actions except for deletion will be performed on the underlying objects. type: boolean persistentVolumeClaimRetentionPolicy: description: |- The field controls if and how PVCs are deleted during the lifecycle of a StatefulSet. The default behavior is all PVCs are retained. This is an alpha field from kubernetes 1.23 until 1.26 and a beta field from 1.26. It requires enabling the StatefulSetAutoDeletePVC feature gate. properties: whenDeleted: description: |- WhenDeleted specifies what happens to PVCs created from StatefulSet VolumeClaimTemplates when the StatefulSet is deleted. The default policy of `Retain` causes PVCs to not be affected by StatefulSet deletion. The `Delete` policy causes those PVCs to be deleted. type: string whenScaled: description: |- WhenScaled specifies what happens to PVCs created from StatefulSet VolumeClaimTemplates when the StatefulSet is scaled down. The default policy of `Retain` causes PVCs to not be affected by a scaledown. The `Delete` policy causes the associated PVCs for any excess pods above the replica count to be deleted. type: string type: object podMetadata: description: |- PodMetadata configures labels and annotations which are propagated to the Prometheus pods. The following items are reserved and cannot be overridden: * "prometheus" label, set to the name of the Prometheus object. * "app.kubernetes.io/instance" label, set to the name of the Prometheus object. * "app.kubernetes.io/managed-by" label, set to "prometheus-operator". * "app.kubernetes.io/name" label, set to "prometheus". * "app.kubernetes.io/version" label, set to the Prometheus version. * "operator.prometheus.io/name" label, set to the name of the Prometheus object. * "operator.prometheus.io/shard" label, set to the shard number of the Prometheus object. * "kubectl.kubernetes.io/default-container" annotation, set to "prometheus". 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. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/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: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/ type: string type: object podMonitorNamespaceSelector: description: |- Namespaces to match for PodMonitors discovery. An empty label selector matches all namespaces. A null label selector (default value) matches the current namespace only. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic podMonitorSelector: description: |- PodMonitors to be selected for target discovery. An empty label selector matches all objects. A null label selector matches no objects. If `spec.serviceMonitorSelector`, `spec.podMonitorSelector`, `spec.probeSelector` and `spec.scrapeConfigSelector` are null, the Prometheus configuration is unmanaged. The Prometheus operator will ensure that the Prometheus configuration's Secret exists, but it is the responsibility of the user to provide the raw gzipped Prometheus configuration under the `prometheus.yaml.gz` key. This behavior is *deprecated* and will be removed in the next major version of the custom resource definition. It is recommended to use `spec.additionalScrapeConfigs` instead. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic podTargetLabels: description: |- PodTargetLabels are appended to the `spec.podTargetLabels` field of all PodMonitor and ServiceMonitor objects. items: type: string type: array portName: default: web description: |- Port name used for the pods and governing service. Default: "web" type: string priorityClassName: description: Priority class assigned to the Pods. type: string probeNamespaceSelector: description: |- Namespaces to match for Probe discovery. An empty label selector matches all namespaces. A null label selector matches the current namespace only. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic probeSelector: description: |- Probes to be selected for target discovery. An empty label selector matches all objects. A null label selector matches no objects. If `spec.serviceMonitorSelector`, `spec.podMonitorSelector`, `spec.probeSelector` and `spec.scrapeConfigSelector` are null, the Prometheus configuration is unmanaged. The Prometheus operator will ensure that the Prometheus configuration's Secret exists, but it is the responsibility of the user to provide the raw gzipped Prometheus configuration under the `prometheus.yaml.gz` key. This behavior is *deprecated* and will be removed in the next major version of the custom resource definition. It is recommended to use `spec.additionalScrapeConfigs` instead. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic prometheusExternalLabelName: description: |- Name of Prometheus external label used to denote the Prometheus instance name. The external label will _not_ be added when the field is set to the empty string (`""`). Default: "prometheus" type: string reloadStrategy: description: |- Defines the strategy used to reload the Prometheus configuration. If not specified, the configuration is reloaded using the /-/reload HTTP endpoint. enum: - HTTP - ProcessSignal type: string remoteWrite: description: Defines the list of remote write configurations. items: description: |- RemoteWriteSpec defines the configuration to write samples from Prometheus to a remote endpoint. properties: authorization: description: |- Authorization section for the URL. It requires Prometheus >= v2.26.0 or Thanos >= v0.24.0. Cannot be set at the same time as `sigv4`, `basicAuth`, `oauth2`, or `azureAd`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic credentialsFile: description: File to read a secret from, mutually exclusive with `credentials`. type: string type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object azureAd: description: |- AzureAD for the URL. It requires Prometheus >= v2.45.0 or Thanos >= v0.31.0. Cannot be set at the same time as `authorization`, `basicAuth`, `oauth2`, or `sigv4`. properties: cloud: description: The Azure Cloud. Options are 'AzurePublic', 'AzureChina', or 'AzureGovernment'. enum: - AzureChina - AzureGovernment - AzurePublic type: string managedIdentity: description: |- ManagedIdentity defines the Azure User-assigned Managed identity. Cannot be set at the same time as `oauth` or `sdk`. properties: clientId: description: The client id type: string required: - clientId type: object oauth: description: |- OAuth defines the oauth config that is being used to authenticate. Cannot be set at the same time as `managedIdentity` or `sdk`. It requires Prometheus >= v2.48.0 or Thanos >= v0.31.0. properties: clientId: description: '`clientID` is the clientId of the Azure Active Directory application that is being used to authenticate.' minLength: 1 type: string clientSecret: description: '`clientSecret` specifies a key of a Secret containing the client secret of the Azure Active Directory application that is being used to authenticate.' properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic tenantId: description: '`tenantId` is the tenant ID of the Azure Active Directory application that is being used to authenticate.' minLength: 1 pattern: ^[0-9a-zA-Z-.]+$ type: string required: - clientId - clientSecret - tenantId type: object sdk: description: |- SDK defines the Azure SDK config that is being used to authenticate. See https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication Cannot be set at the same time as `oauth` or `managedIdentity`. It requires Prometheus >= v2.52.0 or Thanos >= v0.36.0. properties: tenantId: description: '`tenantId` is the tenant ID of the azure active directory application that is being used to authenticate.' pattern: ^[0-9a-zA-Z-.]+$ type: string type: object type: object basicAuth: description: |- BasicAuth configuration for the URL. Cannot be set at the same time as `sigv4`, `authorization`, `oauth2`, or `azureAd`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerToken: description: |- *Warning: this field shouldn't be used because the token value appears in clear-text. Prefer using `authorization`.* Deprecated: this will be removed in a future release. type: string bearerTokenFile: description: |- File from which to read bearer token for the URL. Deprecated: this will be removed in a future release. Prefer using `authorization`. type: string enableHTTP2: description: Whether to enable HTTP2. type: boolean followRedirects: description: |- Configure whether HTTP requests follow HTTP 3xx redirects. It requires Prometheus >= v2.26.0 or Thanos >= v0.24.0. type: boolean headers: additionalProperties: type: string description: |- Custom HTTP headers to be sent along with each remote write request. Be aware that headers that are set by Prometheus itself can't be overwritten. It requires Prometheus >= v2.25.0 or Thanos >= v0.24.0. type: object messageVersion: description: |- The Remote Write message's version to use when writing to the endpoint. `Version1.0` corresponds to the `prometheus.WriteRequest` protobuf message introduced in Remote Write 1.0. `Version2.0` corresponds to the `io.prometheus.write.v2.Request` protobuf message introduced in Remote Write 2.0. When `Version2.0` is selected, Prometheus will automatically be configured to append the metadata of scraped metrics to the WAL. Before setting this field, consult with your remote storage provider what message version it supports. It requires Prometheus >= v2.54.0 or Thanos >= v0.37.0. enum: - V1.0 - V2.0 type: string metadataConfig: description: MetadataConfig configures the sending of series metadata to the remote storage. properties: maxSamplesPerSend: description: |- MaxSamplesPerSend is the maximum number of metadata samples per send. It requires Prometheus >= v2.29.0. format: int32 minimum: -1 type: integer send: description: Defines whether metric metadata is sent to the remote storage or not. type: boolean sendInterval: description: Defines how frequently metric metadata is sent to the remote storage. 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 type: object name: description: |- The name of the remote write queue, it must be unique if specified. The name is used in metrics and logging in order to differentiate queues. It requires Prometheus >= v2.15.0 or Thanos >= 0.24.0. type: string noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- OAuth2 configuration for the URL. It requires Prometheus >= v2.27.0 or Thanos >= v0.24.0. Cannot be set at the same time as `sigv4`, `authorization`, `basicAuth`, or `azureAd`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string queueConfig: description: QueueConfig allows tuning of the remote write queue parameters. properties: batchSendDeadline: description: BatchSendDeadline is the maximum time a sample will wait in buffer. 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 capacity: description: |- Capacity is the number of samples to buffer per shard before we start dropping them. type: integer maxBackoff: description: MaxBackoff is the maximum retry delay. 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 maxRetries: description: MaxRetries is the maximum number of times to retry a batch on recoverable errors. type: integer maxSamplesPerSend: description: MaxSamplesPerSend is the maximum number of samples per send. type: integer maxShards: description: MaxShards is the maximum number of shards, i.e. amount of concurrency. type: integer minBackoff: description: MinBackoff is the initial retry delay. Gets doubled for every retry. 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 minShards: description: MinShards is the minimum number of shards, i.e. amount of concurrency. type: integer retryOnRateLimit: description: |- Retry upon receiving a 429 status code from the remote-write storage. This is an *experimental feature*, it may change in any upcoming release in a breaking way. type: boolean sampleAgeLimit: description: |- SampleAgeLimit drops samples older than the limit. It requires Prometheus >= v2.50.0 or Thanos >= v0.32.0. 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 type: object remoteTimeout: description: Timeout for requests to the remote write endpoint. 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 roundRobinDNS: description: |- When enabled: - The remote-write mechanism will resolve the hostname via DNS. - It will randomly select one of the resolved IP addresses and connect to it. When disabled (default behavior): - The Go standard library will handle hostname resolution. - It will attempt connections to each resolved IP address sequentially. Note: The connection timeout applies to the entire resolution and connection process. If disabled, the timeout is distributed across all connection attempts. It requires Prometheus >= v3.1.0 or Thanos >= v0.38.0. type: boolean sendExemplars: description: |- Enables sending of exemplars over remote write. Note that exemplar-storage itself must be enabled using the `spec.enableFeatures` option for exemplars to be scraped in the first place. It requires Prometheus >= v2.27.0 or Thanos >= v0.24.0. type: boolean sendNativeHistograms: description: |- Enables sending of native histograms, also known as sparse histograms over remote write. It requires Prometheus >= v2.40.0 or Thanos >= v0.30.0. type: boolean sigv4: description: |- Sigv4 allows to configures AWS's Signature Verification 4 for the URL. It requires Prometheus >= v2.26.0 or Thanos >= v0.24.0. Cannot be set at the same time as `authorization`, `basicAuth`, `oauth2`, or `azureAd`. properties: accessKey: description: |- AccessKey is the AWS API key. If not specified, the environment variable `AWS_ACCESS_KEY_ID` is used. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic profile: description: Profile is the named AWS profile used to authenticate. type: string region: description: Region is the AWS region. If blank, the region from the default credentials chain used. type: string roleArn: description: RoleArn is the named AWS profile used to authenticate. type: string secretKey: description: |- SecretKey is the AWS API secret. If not specified, the environment variable `AWS_SECRET_ACCESS_KEY` is used. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object tlsConfig: description: TLS Config to use for the URL. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object url: description: The URL of the endpoint to send samples to. minLength: 1 type: string writeRelabelConfigs: description: The list of remote write relabel configurations. items: description: |- RelabelConfig allows dynamic rewriting of the label set for targets, alerts, scraped samples and remote write samples. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. Regex capture groups are available. type: string type: object type: array required: - url type: object type: array remoteWriteReceiverMessageVersions: description: |- List of the protobuf message versions to accept when receiving the remote writes. It requires Prometheus >= v2.54.0. items: enum: - V1.0 - V2.0 type: string minItems: 1 type: array x-kubernetes-list-type: set replicaExternalLabelName: description: |- Name of Prometheus external label used to denote the replica name. The external label will _not_ be added when the field is set to the empty string (`""`). Default: "prometheus_replica" type: string replicas: description: |- Number of replicas of each shard to deploy for a Prometheus deployment. `spec.replicas` multiplied by `spec.shards` is the total number of Pods created. Default: 1 format: int32 type: integer resources: description: Defines the resources requests and limits of the 'prometheus' container. properties: claims: description: |- Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: description: |- Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. type: string request: description: |- Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object routePrefix: description: |- The route prefix Prometheus registers HTTP handlers for. This is useful when using `spec.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 runtime: description: RuntimeConfig configures the values for the Prometheus process behavior properties: goGC: description: |- The Go garbage collection target percentage. Lowering this number may increase the CPU usage. See: https://tip.golang.org/doc/gc-guide#GOGC format: int32 minimum: -1 type: integer type: object sampleLimit: description: |- SampleLimit defines per-scrape limit on number of scraped samples that will be accepted. Only valid in Prometheus versions 2.45.0 and newer. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedSampleLimit. format: int64 type: integer scrapeClasses: description: |- List of scrape classes to expose to scraping objects such as PodMonitors, ServiceMonitors, Probes and ScrapeConfigs. This is an *experimental feature*, it may change in any upcoming release in a breaking way. items: properties: attachMetadata: description: |- AttachMetadata configures additional metadata to the discovered targets. When the scrape object defines its own configuration, it takes precedence over the scrape class configuration. properties: node: description: |- When set to true, Prometheus attaches node metadata to the discovered targets. The Prometheus service account must have the `list` and `watch` permissions on the `Nodes` objects. type: boolean type: object authorization: description: |- Authorization section for the ScrapeClass. It will only apply if the scrape resource doesn't specify any Authorization. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic credentialsFile: description: File to read a secret from, mutually exclusive with `credentials`. type: string type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object default: description: |- Default indicates that the scrape applies to all scrape objects that don't configure an explicit scrape class name. Only one scrape class can be set as the default. type: boolean fallbackScrapeProtocol: description: |- The protocol to use if a scrape returns blank, unparseable, or otherwise invalid Content-Type. It will only apply if the scrape resource doesn't specify any FallbackScrapeProtocol It requires Prometheus >= v3.0.0. enum: - PrometheusProto - OpenMetricsText0.0.1 - OpenMetricsText1.0.0 - PrometheusText0.0.4 - PrometheusText1.0.0 type: string metricRelabelings: description: |- MetricRelabelings configures the relabeling rules to apply to all samples before ingestion. The Operator adds the scrape class metric relabelings defined here. Then the Operator adds the target-specific metric relabelings defined in ServiceMonitors, PodMonitors, Probes and ScrapeConfigs. Then the Operator adds namespace enforcement relabeling rule, specified in '.spec.enforcedNamespaceLabel'. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs items: description: |- RelabelConfig allows dynamic rewriting of the label set for targets, alerts, scraped samples and remote write samples. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. Regex capture groups are available. type: string type: object type: array name: description: Name of the scrape class. minLength: 1 type: string relabelings: description: |- Relabelings configures the relabeling rules to apply to all scrape targets. The Operator automatically adds relabelings for a few standard Kubernetes fields like `__meta_kubernetes_namespace` and `__meta_kubernetes_service_name`. Then the Operator adds the scrape class relabelings defined here. Then the Operator adds the target-specific relabelings defined in the scrape object. 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. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. Regex capture groups are available. type: string type: object type: array tlsConfig: description: |- TLSConfig defines the TLS settings to use for the scrape. When the scrape objects define their own CA, certificate and/or key, they take precedence over the corresponding scrape class fields. For now only the `caFile`, `certFile` and `keyFile` fields are supported. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map scrapeClassicHistograms: description: |- Whether to scrape a classic histogram that is also exposed as a native histogram. Notice: `scrapeClassicHistograms` corresponds to the `always_scrape_classic_histograms` field in the Prometheus configuration. It requires Prometheus >= v3.5.0. type: boolean scrapeConfigNamespaceSelector: description: |- Namespaces to match for ScrapeConfig discovery. An empty label selector matches all namespaces. A null label selector matches the current namespace only. Note that the ScrapeConfig custom resource definition is currently at Alpha level. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic scrapeConfigSelector: description: |- ScrapeConfigs to be selected for target discovery. An empty label selector matches all objects. A null label selector matches no objects. If `spec.serviceMonitorSelector`, `spec.podMonitorSelector`, `spec.probeSelector` and `spec.scrapeConfigSelector` are null, the Prometheus configuration is unmanaged. The Prometheus operator will ensure that the Prometheus configuration's Secret exists, but it is the responsibility of the user to provide the raw gzipped Prometheus configuration under the `prometheus.yaml.gz` key. This behavior is *deprecated* and will be removed in the next major version of the custom resource definition. It is recommended to use `spec.additionalScrapeConfigs` instead. Note that the ScrapeConfig custom resource definition is currently at Alpha level. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic scrapeFailureLogFile: description: |- File to which scrape failures are logged. Reloading the configuration will reopen the file. If the filename has an empty path, e.g. 'file.log', The Prometheus Pods will mount the file into an emptyDir volume at `/var/log/prometheus`. If a full path is provided, e.g. '/var/log/prometheus/file.log', you must mount a volume in the specified directory and it must be writable. It requires Prometheus >= v2.55.0. minLength: 1 type: string scrapeInterval: default: 30s description: |- Interval between consecutive scrapes. Default: "30s" 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 scrapeProtocols: description: |- The protocols to negotiate during a scrape. It tells clients the protocols supported by Prometheus in order of preference (from most to least preferred). If unset, Prometheus uses its default value. It requires Prometheus >= v2.49.0. `PrometheusText1.0.0` requires Prometheus >= v3.0.0. items: description: |- ScrapeProtocol represents a protocol used by Prometheus for scraping metrics. Supported values are: * `OpenMetricsText0.0.1` * `OpenMetricsText1.0.0` * `PrometheusProto` * `PrometheusText0.0.4` * `PrometheusText1.0.0` enum: - PrometheusProto - OpenMetricsText0.0.1 - OpenMetricsText1.0.0 - PrometheusText0.0.4 - PrometheusText1.0.0 type: string type: array x-kubernetes-list-type: set scrapeTimeout: description: |- Number of seconds to wait until a scrape request times out. The value cannot be greater than the scrape interval otherwise the operator will reject the resource. 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 secrets: description: |- Secrets is a list of Secrets in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. Each Secret is added to the StatefulSet definition as a volume named `secret-`. The Secrets are mounted into /etc/prometheus/secrets/ in the 'prometheus' container. items: type: string type: array x-kubernetes-list-type: set securityContext: description: |- SecurityContext holds pod-level security attributes and common container settings. This defaults to the default PodSecurityContext. properties: appArmorProfile: description: |- appArmorProfile is the AppArmor 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 loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost". type: string type: description: |- type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement. type: string required: - type type: object 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: 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---- 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 seLinuxChangePolicy: description: |- seLinuxChangePolicy defines how the container's SELinux label is applied to all volumes used by the Pod. It has no effect on nodes that do not support SELinux or to volumes does not support SELinux. Valid values are "MountOption" and "Recursive". "Recursive" means relabeling of all files on all Pod volumes by the container runtime. This may be slow for large volumes, but allows mixing privileged and unprivileged Pods sharing the same volume on the same node. "MountOption" mounts all eligible Pod volumes with `-o context` mount option. This requires all Pods that share the same volume to use the same SELinux label. It is not possible to share the same volume among privileged and unprivileged Pods. Eligible volumes are in-tree FibreChannel and iSCSI volumes, and all CSI volumes whose CSI driver announces SELinux support by setting spec.seLinuxMount: true in their CSIDriver instance. Other volumes are always re-labelled recursively. "MountOption" value is allowed only when SELinuxMount feature gate is enabled. If not specified and SELinuxMount feature gate is enabled, "MountOption" is used. If not specified and SELinuxMount feature gate is disabled, "MountOption" is used for ReadWriteOncePod volumes and "Recursive" for all other volumes. This field affects only Pods that have SELinux label set, either in PodSecurityContext or in SecurityContext of all containers. All Pods that use the same volume should use the same seLinuxChangePolicy, otherwise some pods can get stuck in ContainerCreating state. Note that this field cannot be set when spec.os.name is windows. type: string 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: 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 and fsGroup (if specified). If the SupplementalGroupsPolicy feature is enabled, the supplementalGroupsPolicy field determines whether these are in addition to or instead of any group memberships defined in the container image. If unspecified, no additional groups are added, though group memberships defined in the container image may still be used, depending on the supplementalGroupsPolicy field. Note that this field cannot be set when spec.os.name is windows. items: format: int64 type: integer type: array x-kubernetes-list-type: atomic supplementalGroupsPolicy: description: |- Defines how supplemental groups of the first container processes are calculated. Valid values are "Merge" and "Strict". If not specified, "Merge" is used. (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled and the container runtime must implement support for this feature. Note that this field cannot be set when spec.os.name is windows. type: string 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 x-kubernetes-list-type: atomic 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 serviceAccountName: description: |- ServiceAccountName is the name of the ServiceAccount to use to run the Prometheus Pods. type: string serviceDiscoveryRole: description: |- Defines the service discovery role used to discover targets from `ServiceMonitor` objects and Alertmanager endpoints. If set, the value should be either "Endpoints" or "EndpointSlice". If unset, the operator assumes the "Endpoints" role. enum: - Endpoints - EndpointSlice type: string serviceMonitorNamespaceSelector: description: |- Namespaces to match for ServicedMonitors discovery. An empty label selector matches all namespaces. A null label selector (default value) matches the current namespace only. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic serviceMonitorSelector: description: |- ServiceMonitors to be selected for target discovery. An empty label selector matches all objects. A null label selector matches no objects. If `spec.serviceMonitorSelector`, `spec.podMonitorSelector`, `spec.probeSelector` and `spec.scrapeConfigSelector` are null, the Prometheus configuration is unmanaged. The Prometheus operator will ensure that the Prometheus configuration's Secret exists, but it is the responsibility of the user to provide the raw gzipped Prometheus configuration under the `prometheus.yaml.gz` key. This behavior is *deprecated* and will be removed in the next major version of the custom resource definition. It is recommended to use `spec.additionalScrapeConfigs` instead. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic serviceName: description: |- The name of the service name used by the underlying StatefulSet(s) as the governing service. If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels. If empty, the operator will create and manage a headless service named `prometheus-operated` for Prometheus resources, or `prometheus-agent-operated` for PrometheusAgent resources. When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each. See https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id for more details. minLength: 1 type: string shards: description: |- Number of shards to distribute the scraped targets onto. `spec.replicas` multiplied by `spec.shards` is the total number of Pods being created. When not defined, the operator assumes only one shard. Note that scaling down shards will not reshard data onto the remaining instances, it must be manually moved. Increasing shards will not reshard data either but it will continue to be available from the same instances. To query globally, use either * Thanos sidecar + querier for query federation and Thanos Ruler for rules. * Remote-write to send metrics to a central location. By default, the sharding of targets is performed on: * The `__address__` target's metadata label for PodMonitor, ServiceMonitor and ScrapeConfig resources. * The `__param_target__` label for Probe resources. Users can define their own sharding implementation by setting the `__tmp_hash` label during the target discovery with relabeling configuration (either in the monitoring resources or via scrape class). You can also disable sharding on a specific target by setting the `__tmp_disable_sharding` label with relabeling configuration. When the label value isn't empty, all Prometheus shards will scrape the target. format: int32 type: integer storage: description: Storage defines the storage used by Prometheus. properties: disableMountSubPath: description: 'Deprecated: subPath usage will be removed in a future release.' type: boolean emptyDir: description: |- EmptyDirVolumeSource to be used by the StatefulSet. If specified, it takes precedence over `ephemeral` and `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: 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: |- EphemeralVolumeSource to be used by the StatefulSet. This is a beta field in k8s 1.21 and GA in 1.15. For lower versions, starting with k8s 1.19, it requires enabling the GenericEphemeralVolume feature gate. More info: https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volumes 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). 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. This field is read-only and no changes will be made by Kubernetes to the PVC after it has been created. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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/volume-attributes-classes/ (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). 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 volumeClaimTemplate: description: |- Defines the PVC spec to be used by the Prometheus StatefulSets. The easiest way to use a volume that cannot be automatically provisioned is to use a label selector alongside manually created PersistentVolumes. 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: 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. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/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: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/ type: string type: object spec: description: |- 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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/volume-attributes-classes/ (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). 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: 'Deprecated: this field is never set.' 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 x-kubernetes-list-type: atomic allocatedResourceStatuses: additionalProperties: description: |- When a controller receives persistentvolume claim update with ClaimResourceStatus for a resource that it does not recognizes, then it should ignore that update and let other controllers handle it. type: string description: "allocatedResourceStatuses stores status of resource being resized for the given PVC.\nKey names follow standard Kubernetes label syntax. Valid values are either:\n\t* Un-prefixed keys:\n\t\t- storage - the capacity of the volume.\n\t* Custom resources must use implementation-defined prefixed names such as \"example.com/my-custom-resource\"\nApart from above values - keys that are unprefixed or have kubernetes.io prefix are considered\nreserved and hence may not be used.\n\nClaimResourceStatus can be in any of following states:\n\t- ControllerResizeInProgress:\n\t\tState set when resize controller starts resizing the volume in control-plane.\n\t- ControllerResizeFailed:\n\t\tState set when resize has failed in resize controller with a terminal error.\n\t- NodeResizePending:\n\t\tState set when resize controller has finished resizing the volume but further resizing of\n\t\tvolume is needed on the node.\n\t- NodeResizeInProgress:\n\t\tState set when kubelet starts resizing the volume.\n\t- NodeResizeFailed:\n\t\tState set when resizing has failed in kubelet with a terminal error. Transient errors don't set\n\t\tNodeResizeFailed.\nFor example: if expanding a PVC for more capacity - this field can be one of the following states:\n\t- pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeInProgress\"\n - pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeFailed\"\n - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizePending\"\n - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeInProgress\"\n - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeFailed\"\nWhen this field is not set, it means that no resize operation is in progress for the given PVC.\n\nA controller that receives PVC update with previously unknown resourceName or ClaimResourceStatus\nshould ignore the update for the purpose it was designed. For example - a controller that\nonly is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid\nresources associated with PVC.\n\nThis is an alpha field and requires enabling RecoverVolumeExpansionFailure feature." type: object x-kubernetes-map-type: granular 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 tracks the resources allocated to a PVC including its capacity.\nKey names follow standard Kubernetes label syntax. Valid values are either:\n\t* Un-prefixed keys:\n\t\t- storage - the capacity of the volume.\n\t* Custom resources must use implementation-defined prefixed names such as \"example.com/my-custom-resource\"\nApart from above values - keys that are unprefixed or have kubernetes.io prefix are considered\nreserved and hence may not be used.\n\nCapacity reported here may be larger than the actual capacity when a volume expansion operation\nis requested.\nFor storage quota, the larger value from allocatedResources and PVC.spec.resources is used.\nIf allocatedResources is not set, PVC.spec.resources alone is used for quota calculation.\nIf a volume expansion capacity request is lowered, allocatedResources is only\nlowered if there are no expansion operations in progress and if the actual volume capacity\nis equal or lower than the requested capacity.\n\nA controller that receives PVC update with previously unknown resourceName\nshould ignore the update for the purpose it was designed. For example - a controller that\nonly is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid\nresources associated with PVC.\n\nThis 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 'Resizing'. items: description: PersistentVolumeClaimCondition contains 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 "Resizing" that means the underlying persistent volume is being resized. type: string status: description: |- Status is the status of the condition. Can be True, False, Unknown. More info: https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/persistent-volume-claim-v1/#:~:text=state%20of%20pvc-,conditions.status,-(string)%2C%20required type: string type: description: |- Type is the type of the condition. More info: https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/persistent-volume-claim-v1/#:~:text=set%20to%20%27ResizeStarted%27.-,PersistentVolumeClaimCondition,-contains%20details%20about type: string required: - status - type type: object type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map currentVolumeAttributesClassName: description: |- currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using. When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim This is a beta field and requires enabling VolumeAttributesClass feature (off by default). type: string modifyVolumeStatus: description: |- ModifyVolumeStatus represents the status object of ControllerModifyVolume operation. When this is unset, there is no ModifyVolume operation being attempted. This is a beta field and requires enabling VolumeAttributesClass feature (off by default). properties: status: description: "status is the status of the ControllerModifyVolume operation. It can be in any of following states:\n - Pending\n Pending indicates that the PersistentVolumeClaim cannot be modified due to unmet requirements, such as\n the specified VolumeAttributesClass not existing.\n - InProgress\n InProgress indicates that the volume is being modified.\n - Infeasible\n Infeasible indicates that the request has been rejected as invalid by the CSI driver. To\n\t resolve the error, a valid VolumeAttributesClass needs to be specified.\nNote: New statuses can be added in the future. Consumers should check for unknown statuses and fail appropriately." type: string targetVolumeAttributesClassName: description: targetVolumeAttributesClassName is the name of the VolumeAttributesClass the PVC currently being reconciled type: string required: - status type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string type: object type: object type: object targetLimit: description: |- TargetLimit defines a limit on the number of scraped targets that will be accepted. Only valid in Prometheus versions 2.45.0 and newer. Note that the global limit only applies to scrape objects that don't specify an explicit limit value. If you want to enforce a maximum limit for all scrape objects, refer to enforcedTargetLimit. format: int64 type: integer terminationGracePeriodSeconds: description: |- Optional duration in seconds the pod needs to terminate gracefully. Value must be non-negative integer. The value zero indicates stop immediately via the kill signal (no opportunity to shut down) which may lead to data corruption. Defaults to 600 seconds. format: int64 minimum: 0 type: integer tolerations: description: Defines the Pods' tolerations if specified. 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: Defines the pod's topology spread constraints if specified. items: properties: additionalLabelSelectors: description: Defines what Prometheus Operator managed labels should be added to labelSelector on the topologySpreadConstraint. enum: - OnResource - OnShard type: string labelSelector: description: |- LabelSelector is used to find matching pods. Pods that match this label selector are counted to determine the number of pods in their corresponding topology domain. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. MatchLabelKeys cannot be set when LabelSelector isn't set. Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. 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. 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. format: int32 type: integer nodeAffinityPolicy: description: |- NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. type: string nodeTaintsPolicy: description: |- NodeTaintsPolicy indicates how we will treat node taints when calculating pod topology spread skew. Options are: - Honor: nodes without taints, along with tainted nodes for which the incoming pod has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. 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 tracingConfig: description: |- TracingConfig configures tracing in Prometheus. This is an *experimental feature*, it may change in any upcoming release in a breaking way. properties: clientType: description: Client used to export the traces. Supported values are `http` or `grpc`. enum: - http - grpc type: string compression: description: Compression key for supported compression types. The only supported value is `gzip`. enum: - gzip type: string endpoint: description: Endpoint to send the traces to. Should be provided in format :. minLength: 1 type: string headers: additionalProperties: type: string description: Key-value pairs to be used as headers associated with gRPC or HTTP requests. type: object insecure: description: If disabled, the client will use a secure connection. type: boolean samplingFraction: anyOf: - type: integer - type: string description: Sets the probability a given trace will be sampled. Must be a float from 0 through 1. pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true timeout: description: Maximum time the exporter will wait for each batch export. 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 tlsConfig: description: TLS Config to use when sending traces. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - endpoint type: object tsdb: description: |- Defines the runtime reloadable configuration of the timeseries database(TSDB). It requires Prometheus >= v2.39.0 or PrometheusAgent >= v2.54.0. properties: outOfOrderTimeWindow: description: |- Configures how old an out-of-order/out-of-bounds sample can be with respect to the TSDB max time. An out-of-order/out-of-bounds sample is ingested into the TSDB as long as the timestamp of the sample is >= (TSDB.MaxTime - outOfOrderTimeWindow). This is an *experimental feature*, it may change in any upcoming release in a breaking way. It requires Prometheus >= v2.39.0 or PrometheusAgent >= v2.54.0. 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 type: object version: description: |- Version of Prometheus being deployed. The operator uses this information to generate the Prometheus StatefulSet + configuration files. If not specified, the operator assumes the latest upstream version of Prometheus available at the time when the version of the operator was released. type: string volumeMounts: description: |- VolumeMounts allows the configuration of additional VolumeMounts. VolumeMounts will be appended to other VolumeMounts in the 'prometheus' 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. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None). 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 recursiveReadOnly: description: |- RecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled. type: string 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 the 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. properties: awsElasticBlockStore: description: |- awsElasticBlockStore represents an AWS Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Deprecated: AWSElasticBlockStore is deprecated. All operations for the in-tree awsElasticBlockStore type are redirected to the ebs.csi.aws.com CSI driver. 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 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. Deprecated: AzureDisk is deprecated. All operations for the in-tree azureDisk type are redirected to the disk.csi.azure.com CSI driver. 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: default: ext4 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: default: false 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. Deprecated: AzureFile is deprecated. All operations for the in-tree azureFile type are redirected to the file.csi.azure.com CSI driver. 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. Deprecated: CephFS is deprecated and the in-tree cephfs type is no longer supported. 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: Cinder is deprecated. All operations for the in-tree cinder type are redirected to the cinder.csi.openstack.org CSI driver. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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 x-kubernetes-list-type: atomic name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: 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. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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, namespace and uid 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 x-kubernetes-list-type: atomic 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. 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). Use PersistentVolumeClaim or one of the vendor-specific APIs for volumes that persist for longer than the lifecycle of an individual pod. 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. 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). 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. This field is read-only and no changes will be made by Kubernetes to the PVC after it has been created. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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/volume-attributes-classes/ (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). 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. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic type: object flexVolume: description: |- flexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. Deprecated: FlexVolume is deprecated. Consider using a CSIDriver instead. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: Flocker is deprecated and the in-tree flocker type is no longer supported. 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. Deprecated: GCEPersistentDisk is deprecated. All operations for the in-tree gcePersistentDisk type are redirected to the pd.csi.storage.gke.io CSI driver. 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 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. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported. 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 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 image: description: |- image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided: - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. The volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro) and non-executable files (noexec). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: pullPolicy: description: |- Policy for pulling OCI objects. Possible values are: Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. type: string reference: description: |- Required: Image or artifact reference to be used. Behaves in the same way as pod.spec.containers[*].image. Pull secrets will be assembled in the same way as for the container image by looking up node credentials, SA image pull secrets, and pod spec image pull secrets. 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 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 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: default: default 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: PhotonPersistentDisk is deprecated and the in-tree photonPersistentDisk type is no longer supported. 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. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on. 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. Each entry in this list handles one source. items: description: |- Projection that may be projected along with other supported volume types. Exactly one of these fields must be set. properties: clusterTrustBundle: description: |- ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. Alpha, gated by the ClusterTrustBundleProjection feature gate. ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: 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, namespace and uid 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: 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 x-kubernetes-list-type: atomic type: object quobyte: description: |- quobyte represents a Quobyte mount on the host that shares a pod's lifetime. Deprecated: Quobyte is deprecated and the in-tree quobyte type is no longer supported. 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. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. 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 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: default: /etc/ceph/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 x-kubernetes-list-type: atomic pool: default: rbd 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string type: object x-kubernetes-map-type: atomic user: default: admin 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. Deprecated: ScaleIO is deprecated and the in-tree scaleIO type is no longer supported. properties: fsType: default: xfs 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string type: object x-kubernetes-map-type: atomic sslEnabled: description: sslEnabled Flag enable/disable SSL communication with Gateway, default false type: boolean storageMode: default: ThinProvisioned 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 x-kubernetes-list-type: atomic 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. Deprecated: StorageOS is deprecated and the in-tree storageos type is no longer supported. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: VsphereVolume is deprecated. All operations for the in-tree vsphereVolume type are redirected to the csi.vsphere.vmware.com CSI driver. 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 walCompression: description: |- Configures compression of the write-ahead log (WAL) using Snappy. WAL compression is enabled by default for Prometheus >= 2.20.0 Requires Prometheus v2.11.0 and above. type: boolean web: description: Defines the configuration of the Prometheus web server. properties: httpConfig: description: Defines HTTP parameters for web server. properties: headers: description: List of headers that can be added to HTTP responses. properties: contentSecurityPolicy: description: |- Set the Content-Security-Policy header to HTTP responses. Unset if blank. type: string strictTransportSecurity: description: |- Set the Strict-Transport-Security header to HTTP responses. Unset if blank. Please make sure that you use this with care as this header might force browsers to load Prometheus and the other applications hosted on the same domain and subdomains over HTTPS. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security type: string xContentTypeOptions: description: |- Set the X-Content-Type-Options header to HTTP responses. Unset if blank. Accepted value is nosniff. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options enum: - "" - NoSniff type: string xFrameOptions: description: |- Set the X-Frame-Options header to HTTP responses. Unset if blank. Accepted values are deny and sameorigin. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options enum: - "" - Deny - SameOrigin type: string xXSSProtection: description: |- Set the X-XSS-Protection header to all responses. Unset if blank. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection type: string type: object http2: description: |- Enable HTTP/2 support. Note that HTTP/2 is only supported with TLS. When TLSConfig is not configured, HTTP/2 will be disabled. Whenever the value of the field changes, a rolling update will be triggered. type: boolean type: object maxConnections: description: |- Defines the maximum number of simultaneous connections A zero value means that Prometheus doesn't accept any incoming connection. format: int32 minimum: 0 type: integer pageTitle: description: The prometheus web page title. type: string tlsConfig: description: Defines the TLS parameters for HTTPS. properties: cert: description: |- Secret or ConfigMap containing the TLS certificate for the web server. Either `keySecret` or `keyFile` must be defined. It is mutually exclusive with `certFile`. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object certFile: description: |- Path to the TLS certificate file in the container for the web server. Either `keySecret` or `keyFile` must be defined. It is mutually exclusive with `cert`. type: string cipherSuites: description: |- List of supported cipher suites for TLS versions up to TLS 1.2. If not defined, the Go default cipher suites are used. Available cipher suites are documented in the Go documentation: https://golang.org/pkg/crypto/tls/#pkg-constants items: type: string type: array client_ca: description: |- Secret or ConfigMap containing the CA certificate for client certificate authentication to the server. It is mutually exclusive with `clientCAFile`. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientAuthType: description: |- The server policy for client TLS authentication. For more detail on clientAuth options: https://golang.org/pkg/crypto/tls/#ClientAuthType type: string clientCAFile: description: |- Path to the CA certificate file for client certificate authentication to the server. It is mutually exclusive with `client_ca`. type: string curvePreferences: description: |- Elliptic curves that will be used in an ECDHE handshake, in preference order. Available curves are documented in the Go documentation: https://golang.org/pkg/crypto/tls/#CurveID items: type: string type: array keyFile: description: |- Path to the TLS private key file in the container for the web server. If defined, either `cert` or `certFile` must be defined. It is mutually exclusive with `keySecret`. type: string keySecret: description: |- Secret containing the TLS private key for the web server. Either `cert` or `certFile` must be defined. It is mutually exclusive with `keyFile`. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: Maximum TLS version that is acceptable. type: string minVersion: description: Minimum TLS version that is acceptable. type: string preferServerCipherSuites: description: |- Controls whether the server selects the client's most preferred cipher suite, or the server's most preferred cipher suite. If true then the server's preference, as expressed in the order of elements in cipherSuites, is used. type: boolean type: object type: object type: object x-kubernetes-validations: - message: replicas cannot be set when mode is DaemonSet rule: '!(has(self.mode) && self.mode == ''DaemonSet'' && has(self.replicas))' - message: storage cannot be set when mode is DaemonSet rule: '!(has(self.mode) && self.mode == ''DaemonSet'' && has(self.storage))' - message: shards cannot be greater than 1 when mode is DaemonSet rule: '!(has(self.mode) && self.mode == ''DaemonSet'' && has(self.shards) && self.shards > 1)' - message: persistentVolumeClaimRetentionPolicy cannot be set when mode is DaemonSet rule: '!(has(self.mode) && self.mode == ''DaemonSet'' && has(self.persistentVolumeClaimRetentionPolicy))' - message: scrapeConfigSelector cannot be set when mode is DaemonSet rule: '!(has(self.mode) && self.mode == ''DaemonSet'' && has(self.scrapeConfigSelector))' - message: probeSelector cannot be set when mode is DaemonSet rule: '!(has(self.mode) && self.mode == ''DaemonSet'' && has(self.probeSelector))' status: description: |- Most recent observed status of the Prometheus cluster. Read-only. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status properties: availableReplicas: description: |- Total number of available pods (ready for at least minReadySeconds) targeted by this Prometheus deployment. format: int32 type: integer conditions: description: The current state of the Prometheus deployment. items: description: |- Condition represents the state of the resources associated with the Prometheus, Alertmanager or ThanosRuler resource. properties: lastTransitionTime: description: lastTransitionTime is the time of the last update to the current status property. format: date-time type: string message: description: Human-readable message indicating details for the condition's last transition. 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[].observedGeneration` is 9, the condition is out of date with respect to the current state of the instance. format: int64 type: integer reason: description: Reason for the condition's last transition. type: string status: description: Status of the condition. minLength: 1 type: string type: description: Type of the condition being reported. minLength: 1 type: string required: - lastTransitionTime - status - type type: object type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map paused: description: |- Represents whether any actions on the underlying managed objects are being performed. Only delete actions will be performed. type: boolean replicas: description: |- Total number of non-terminated pods targeted by this Prometheus deployment (their labels match the selector). format: int32 type: integer selector: description: The selector used to match the pods targeted by this Prometheus resource. type: string shardStatuses: description: The list has one entry per shard. Each entry provides a summary of the shard status. items: properties: availableReplicas: description: |- Total number of available pods (ready for at least minReadySeconds) targeted by this shard. format: int32 type: integer replicas: description: Total number of pods targeted by this shard. format: int32 type: integer shardID: description: Identifier of the shard. type: string unavailableReplicas: description: Total number of unavailable pods targeted by this shard. format: int32 type: integer updatedReplicas: description: |- Total number of non-terminated pods targeted by this shard that have the desired spec. format: int32 type: integer required: - availableReplicas - replicas - shardID - unavailableReplicas - updatedReplicas type: object type: array x-kubernetes-list-map-keys: - shardID x-kubernetes-list-type: map shards: description: Shards is the most recently observed number of shards. format: int32 type: integer unavailableReplicas: description: Total number of unavailable pods targeted by this Prometheus deployment. format: int32 type: integer updatedReplicas: description: |- Total number of non-terminated pods targeted by this Prometheus deployment 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: scale: labelSelectorPath: .status.selector specReplicasPath: .spec.shards statusReplicasPath: .status.shards status: {} ================================================ FILE: hack/config/monitoring/crds/0prometheusruleCustomResourceDefinition.yaml ================================================ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 operator.prometheus.io/version: 0.85.0 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: |- The `PrometheusRule` custom resource definition (CRD) defines [alerting](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/) and [recording](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/) rules to be evaluated by `Prometheus` or `ThanosRuler` objects. `Prometheus` and `ThanosRuler` objects select `PrometheusRule` objects using label and namespace 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: 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 labels: additionalProperties: type: string description: |- Labels to add or overwrite before storing the result for its rules. The labels defined at the rule level take precedence. It requires Prometheus >= 3.0.0. The field is ignored for Thanos Ruler. type: object 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 query_offset: description: |- Defines the offset the rule evaluation timestamp of this particular group by the specified duration into the past. It requires Prometheus >= v2.53.0. It is not supported for ThanosRuler. 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 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 ================================================ FILE: hack/config/monitoring/crds/0scrapeconfigCustomResourceDefinition.yaml ================================================ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 operator.prometheus.io/version: 0.85.0 name: scrapeconfigs.monitoring.coreos.com spec: group: monitoring.coreos.com names: categories: - prometheus-operator kind: ScrapeConfig listKind: ScrapeConfigList plural: scrapeconfigs shortNames: - scfg singular: scrapeconfig scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: description: |- ScrapeConfig defines a namespaced Prometheus scrape_config to be aggregated across multiple namespaces into the Prometheus configuration. 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: ScrapeConfigSpec is a specification of the desired configuration for a scrape configuration. properties: authorization: description: Authorization header to use on every scrape request. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object azureSDConfigs: description: AzureSDConfigs defines a list of Azure service discovery configurations. items: description: |- AzureSDConfig allow retrieving scrape targets from Azure VMs. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#azure_sd_config properties: authenticationMethod: description: |- # The authentication method, either `OAuth` or `ManagedIdentity` or `SDK`. See https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview SDK authentication method uses environment variables by default. See https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication enum: - OAuth - ManagedIdentity - SDK type: string authorization: description: |- Authorization header configuration to authenticate against the target HTTP endpoint. Cannot be set at the same time as `oAuth2`, or `basicAuth`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth information to authenticate against the target HTTP endpoint. More info: https://prometheus.io/docs/operating/configuration/#endpoints Cannot be set at the same time as `authorization`, or `oAuth2`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientID: description: Optional client ID. Only required with the OAuth authentication method. minLength: 1 type: string clientSecret: description: Optional client secret. Only required with the OAuth authentication method. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic enableHTTP2: description: Whether to enable HTTP2. type: boolean environment: description: The Azure environment. minLength: 1 type: string followRedirects: description: Configure whether HTTP requests follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- Optional OAuth 2.0 configuration to authenticate against the target HTTP endpoint. Cannot be set at the same time as `authorization`, or `basicAuth`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object port: description: |- The port to scrape metrics from. If using the public IP address, this must instead be specified in the relabeling rule. format: int32 maximum: 65535 minimum: 0 type: integer proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: RefreshInterval configures the refresh interval at which Prometheus will re-read the instance list. 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 resourceGroup: description: |- Optional resource group name. Limits discovery to this resource group. Requires Prometheus v2.35.0 and above minLength: 1 type: string subscriptionID: description: The subscription ID. Always required. minLength: 1 type: string tenantID: description: Optional tenant ID. Only required with the OAuth authentication method. minLength: 1 type: string tlsConfig: description: TLS configuration applying to the target HTTP 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - subscriptionID type: object type: array basicAuth: description: BasicAuth information to use on every scrape request. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object consulSDConfigs: description: ConsulSDConfigs defines a list of Consul service discovery configurations. items: description: |- ConsulSDConfig defines a Consul service discovery configuration See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#consul_sd_config properties: allowStale: description: |- Allow stale Consul results (see https://www.consul.io/api/features/consistency.html). Will reduce load on Consul. If unset, Prometheus uses its default value. type: boolean authorization: description: |- Optional Authorization header configuration to authenticate against the Consul Server. Cannot be set at the same time as `basicAuth`, or `oauth2`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- Optional BasicAuth information to authenticate against the Consul Server. More info: https://prometheus.io/docs/operating/configuration/#endpoints Cannot be set at the same time as `authorization`, or `oauth2`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object datacenter: description: Consul Datacenter name, if not provided it will use the local Consul Agent Datacenter. minLength: 1 type: string enableHTTP2: description: |- Whether to enable HTTP2. If unset, Prometheus uses its default value. type: boolean filter: description: |- Filter expression used to filter the catalog results. See https://www.consul.io/api-docs/catalog#list-services It requires Prometheus >= 3.0.0. minLength: 1 type: string followRedirects: description: |- Configure whether HTTP requests follow HTTP 3xx redirects. If unset, Prometheus uses its default value. type: boolean namespace: description: |- Namespaces are only supported in Consul Enterprise. It requires Prometheus >= 2.28.0. minLength: 1 type: string noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string nodeMeta: additionalProperties: type: string description: |- Node metadata key/value pairs to filter nodes for a given service. Starting with Consul 1.14, it is recommended to use `filter` with the `NodeMeta` selector instead. type: object x-kubernetes-map-type: atomic oauth2: description: |- Optional OAuth2.0 configuration. Cannot be set at the same time as `basicAuth`, or `authorization`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object partition: description: Admin Partitions are only supported in Consul Enterprise. minLength: 1 type: string pathPrefix: description: |- Prefix for URIs for when consul is behind an API gateway (reverse proxy). It requires Prometheus >= 2.45.0. minLength: 1 type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: |- The time after which the provided names are refreshed. On large setup it might be a good idea to increase this value because the catalog will change all the time. If unset, Prometheus uses its default value. 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 scheme: description: HTTP Scheme default "http" enum: - HTTP - HTTPS type: string server: description: Consul server address. A valid string consisting of a hostname or IP followed by an optional port number. minLength: 1 type: string services: description: A list of services for which targets are retrieved. If omitted, all services are scraped. items: type: string type: array x-kubernetes-list-type: set tagSeparator: description: |- The string by which Consul tags are joined into the tag label. If unset, Prometheus uses its default value. minLength: 1 type: string tags: description: |- An optional list of tags used to filter nodes for a given service. Services must contain all tags in the list. Starting with Consul 1.14, it is recommended to use `filter` with the `ServiceTags` selector instead. items: type: string type: array x-kubernetes-list-type: set tlsConfig: description: TLS configuration to connect to the Consul API. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenRef: description: Consul ACL TokenRef, if not provided it will use the ACL from the local Consul Agent. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic required: - server type: object type: array convertClassicHistogramsToNHCB: description: |- Whether to convert all scraped classic histograms into a native histogram with custom buckets. It requires Prometheus >= v3.0.0. type: boolean digitalOceanSDConfigs: description: DigitalOceanSDConfigs defines a list of DigitalOcean service discovery configurations. items: description: |- DigitalOceanSDConfig allow retrieving scrape targets from DigitalOcean's Droplets API. This service discovery uses the public IPv4 address by default, by that can be changed with relabeling See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#digitalocean_sd_config properties: authorization: description: |- Authorization header configuration to authenticate against the DigitalOcean API. Cannot be set at the same time as `oauth2`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object enableHTTP2: description: Whether to enable HTTP2. type: boolean followRedirects: description: Configure whether HTTP requests follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- Optional OAuth 2.0 configuration. Cannot be set at the same time as `authorization`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object port: description: The port to scrape metrics from. format: int32 maximum: 65535 minimum: 0 type: integer proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: Refresh interval to re-read the instance list. 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 tlsConfig: description: TLS configuration applying to the target HTTP 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object type: array dnsSDConfigs: description: DNSSDConfigs defines a list of DNS service discovery configurations. items: description: |- DNSSDConfig allows specifying a set of DNS domain names which are periodically queried to discover a list of targets. The DNS servers to be contacted are read from /etc/resolv.conf. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#dns_sd_config properties: names: description: A list of DNS domain names to be queried. items: minLength: 1 type: string minItems: 1 type: array port: description: |- The port number used if the query type is not SRV Ignored for SRV records format: int32 maximum: 65535 minimum: 0 type: integer refreshInterval: description: |- RefreshInterval configures the time after which the provided names are refreshed. If not set, Prometheus uses its default value. 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 type: description: |- The type of DNS query to perform. One of SRV, A, AAAA, MX or NS. If not set, Prometheus uses its default value. When set to NS, it requires Prometheus >= v2.49.0. When set to MX, it requires Prometheus >= v2.38.0 enum: - A - AAAA - MX - NS - SRV type: string required: - names type: object type: array dockerSDConfigs: description: DockerSDConfigs defines a list of Docker service discovery configurations. items: description: |- Docker SD configurations allow retrieving scrape targets from Docker Engine hosts. This SD discovers "containers" and will create a target for each network IP and port the container is configured to expose. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#docker_sd_config properties: authorization: description: |- Authorization header configuration to authenticate against the Docker API. Cannot be set at the same time as `oauth2`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: BasicAuth information to use on every scrape request. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object enableHTTP2: description: Whether to enable HTTP2. type: boolean filters: description: Optional filters to limit the discovery process to a subset of the available resources. items: description: Filter name and value pairs to limit the discovery process to a subset of available resources. properties: name: description: Name of the Filter. type: string values: description: Value to filter on. items: minLength: 1 type: string minItems: 1 type: array x-kubernetes-list-type: set required: - name - values type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map followRedirects: description: Configure whether HTTP requests follow HTTP 3xx redirects. type: boolean host: description: Address of the docker daemon minLength: 1 type: string hostNetworkingHost: description: The host to use if the container is in host networking mode. minLength: 1 type: string matchFirstNetwork: description: |- Configure whether to match the first network if the container has multiple networks defined. If unset, Prometheus uses true by default. It requires Prometheus >= v2.54.1. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- Optional OAuth 2.0 configuration. Cannot be set at the same time as `authorization`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object port: description: The port to scrape metrics from. format: int32 maximum: 65535 minimum: 0 type: integer proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: Time after which the container is refreshed. 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 tlsConfig: description: TLS configuration applying to the target HTTP 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - host type: object type: array dockerSwarmSDConfigs: description: DockerswarmSDConfigs defines a list of Dockerswarm service discovery configurations. items: description: |- DockerSwarmSDConfig configurations allow retrieving scrape targets from Docker Swarm engine. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#dockerswarm_sd_config properties: authorization: description: Authorization header configuration to authenticate against the target HTTP 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: Optional HTTP basic authentication information. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object enableHTTP2: description: Whether to enable HTTP2. type: boolean filters: description: |- Optional filters to limit the discovery process to a subset of available resources. The available filters are listed in the upstream documentation: Services: https://docs.docker.com/engine/api/v1.40/#operation/ServiceList Tasks: https://docs.docker.com/engine/api/v1.40/#operation/TaskList Nodes: https://docs.docker.com/engine/api/v1.40/#operation/NodeList items: description: Filter name and value pairs to limit the discovery process to a subset of available resources. properties: name: description: Name of the Filter. type: string values: description: Value to filter on. items: minLength: 1 type: string minItems: 1 type: array x-kubernetes-list-type: set required: - name - values type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map followRedirects: description: Configure whether HTTP requests follow HTTP 3xx redirects. type: boolean host: description: Address of the Docker daemon pattern: ^[a-zA-Z][a-zA-Z0-9+.-]*://.+$ type: string noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- Optional OAuth 2.0 configuration. Cannot be set at the same time as `authorization`, or `basicAuth`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object port: description: |- The port to scrape metrics from, when `role` is nodes, and for discovered tasks and services that don't have published ports. format: int32 maximum: 65535 minimum: 0 type: integer proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: The time after which the service discovery data is refreshed. 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 role: description: Role of the targets to retrieve. Must be `Services`, `Tasks`, or `Nodes`. enum: - Services - Tasks - Nodes type: string tlsConfig: description: TLS configuration to use on every scrape request 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - host - role type: object type: array ec2SDConfigs: description: EC2SDConfigs defines a list of EC2 service discovery configurations. items: description: |- EC2SDConfig allow retrieving scrape targets from AWS EC2 instances. The private IP address is used by default, but may be changed to the public IP address with relabeling. The IAM credentials used must have the ec2:DescribeInstances permission to discover scrape targets See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#ec2_sd_config The EC2 service discovery requires AWS API keys or role ARN for authentication. BasicAuth, Authorization and OAuth2 fields are not present on purpose. properties: accessKey: description: AccessKey is the AWS API key. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic enableHTTP2: description: |- Whether to enable HTTP2. It requires Prometheus >= v2.41.0 type: boolean filters: description: |- Filters can be used optionally to filter the instance list by other criteria. Available filter criteria can be found here: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html Filter API documentation: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Filter.html It requires Prometheus >= v2.3.0 items: description: Filter name and value pairs to limit the discovery process to a subset of available resources. properties: name: description: Name of the Filter. type: string values: description: Value to filter on. items: minLength: 1 type: string minItems: 1 type: array x-kubernetes-list-type: set required: - name - values type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map followRedirects: description: |- Configure whether HTTP requests follow HTTP 3xx redirects. It requires Prometheus >= v2.41.0 type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string port: description: |- The port to scrape metrics from. If using the public IP address, this must instead be specified in the relabeling rule. format: int32 maximum: 65535 minimum: 0 type: integer proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: RefreshInterval configures the refresh interval at which Prometheus will re-read the instance list. 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 region: description: The AWS region. minLength: 1 type: string roleARN: description: AWS Role ARN, an alternative to using AWS API keys. minLength: 1 type: string secretKey: description: SecretKey is the AWS API secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic tlsConfig: description: |- TLS configuration to connect to the AWS EC2 API. It requires Prometheus >= v2.41.0 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object type: array enableCompression: description: |- When false, Prometheus will request uncompressed response from the scraped target. It requires Prometheus >= v2.49.0. If unset, Prometheus uses true by default. type: boolean enableHTTP2: description: Whether to enable HTTP2. type: boolean eurekaSDConfigs: description: EurekaSDConfigs defines a list of Eureka service discovery configurations. items: description: |- Eureka SD configurations allow retrieving scrape targets using the Eureka REST API. Prometheus will periodically check the REST endpoint and create a target for every app instance. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#eureka_sd_config properties: authorization: description: Authorization header to use on every scrape request. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: BasicAuth information to use on every scrape request. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object enableHTTP2: description: Whether to enable HTTP2. type: boolean followRedirects: description: Configure whether HTTP requests follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- Optional OAuth 2.0 configuration. Cannot be set at the same time as `authorization` or `basic_auth`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: Refresh interval to re-read the instance list. 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 server: description: The URL to connect to the Eureka server. minLength: 1 type: string tlsConfig: description: TLS configuration applying to the target HTTP 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - server type: object type: array fallbackScrapeProtocol: description: |- The protocol to use if a scrape returns blank, unparseable, or otherwise invalid Content-Type. It requires Prometheus >= v3.0.0. enum: - PrometheusProto - OpenMetricsText0.0.1 - OpenMetricsText1.0.0 - PrometheusText0.0.4 - PrometheusText1.0.0 type: string fileSDConfigs: description: FileSDConfigs defines a list of file service discovery configurations. items: description: |- FileSDConfig defines a Prometheus file service discovery configuration See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#file_sd_config properties: files: description: |- List of files to be used for file discovery. Recommendation: use absolute paths. While relative paths work, the prometheus-operator project makes no guarantees about the working directory where the configuration file is stored. Files must be mounted using Prometheus.ConfigMaps or Prometheus.Secrets. items: description: SDFile represents a file used for service discovery pattern: ^[^*]*(\*[^/]*)?\.(json|yml|yaml|JSON|YML|YAML)$ type: string minItems: 1 type: array x-kubernetes-list-type: set refreshInterval: description: RefreshInterval configures the refresh interval at which Prometheus will reload the content of the files. 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 required: - files type: object type: array gceSDConfigs: description: GCESDConfigs defines a list of GCE service discovery configurations. items: description: |- GCESDConfig configures scrape targets from GCP GCE instances. The private IP address is used by default, but may be changed to the public IP address with relabeling. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config The GCE service discovery will load the Google Cloud credentials from the file specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable. See https://cloud.google.com/kubernetes-engine/docs/tutorials/authenticating-to-cloud-platform A pre-requisite for using GCESDConfig is that a Secret containing valid Google Cloud credentials is mounted into the Prometheus or PrometheusAgent pod via the `.spec.secrets` field and that the GOOGLE_APPLICATION_CREDENTIALS environment variable is set to /etc/prometheus/secrets//. properties: filter: description: |- Filter can be used optionally to filter the instance list by other criteria Syntax of this filter is described in the filter query parameter section: https://cloud.google.com/compute/docs/reference/latest/instances/list minLength: 1 type: string port: description: |- The port to scrape metrics from. If using the public IP address, this must instead be specified in the relabeling rule. format: int32 maximum: 65535 minimum: 0 type: integer project: description: The Google Cloud Project ID minLength: 1 type: string refreshInterval: description: RefreshInterval configures the refresh interval at which Prometheus will re-read the instance list. 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 tagSeparator: description: The tag separator is used to separate the tags on concatenation minLength: 1 type: string zone: description: The zone of the scrape targets. If you need multiple zones use multiple GCESDConfigs. minLength: 1 type: string required: - project - zone type: object type: array hetznerSDConfigs: description: HetznerSDConfigs defines a list of Hetzner service discovery configurations. items: description: |- HetznerSDConfig allow retrieving scrape targets from Hetzner Cloud API and Robot API. This service discovery uses the public IPv4 address by default, but that can be changed with relabeling See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#hetzner_sd_config properties: authorization: description: |- Authorization header configuration, required when role is hcloud. Role robot does not support bearer token authentication. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth information to use on every scrape request, required when role is robot. Role hcloud does not support basic auth. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object enableHTTP2: description: Whether to enable HTTP2. type: boolean followRedirects: description: Configure whether HTTP requests follow HTTP 3xx redirects. type: boolean labelSelector: description: |- Label selector used to filter the servers when fetching them from the API. It requires Prometheus >= v3.5.0. minLength: 1 type: string noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- Optional OAuth 2.0 configuration. Cannot be used at the same time as `basic_auth` or `authorization`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object port: description: The port to scrape metrics from. type: integer proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: The time after which the servers are refreshed. 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 role: description: The Hetzner role of entities that should be discovered. enum: - hcloud - Hcloud - robot - Robot type: string tlsConfig: description: TLS configuration to use on every scrape request. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - role type: object type: array 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 httpSDConfigs: description: HTTPSDConfigs defines a list of HTTP service discovery configurations. items: description: |- HTTPSDConfig defines a prometheus HTTP service discovery configuration See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#http_sd_config properties: authorization: description: |- Authorization header configuration to authenticate against the target HTTP endpoint. Cannot be set at the same time as `oAuth2`, or `basicAuth`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth information to authenticate against the target HTTP endpoint. More info: https://prometheus.io/docs/operating/configuration/#endpoints Cannot be set at the same time as `authorization`, or `oAuth2`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object enableHTTP2: description: Whether to enable HTTP2. type: boolean followRedirects: description: Configure whether HTTP requests follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- Optional OAuth 2.0 configuration to authenticate against the target HTTP endpoint. Cannot be set at the same time as `authorization`, or `basicAuth`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: |- RefreshInterval configures the refresh interval at which Prometheus will re-query the endpoint to update the target list. 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 tlsConfig: description: TLS configuration applying to the target HTTP 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object url: description: URL from which the targets are fetched. minLength: 1 pattern: ^http(s)?://.+$ type: string required: - url type: object type: array ionosSDConfigs: description: IonosSDConfigs defines a list of IONOS service discovery configurations. items: description: |- IonosSDConfig configurations allow retrieving scrape targets from IONOS resources. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#ionos_sd_config properties: authorization: description: Authorization` header configuration, required when using IONOS. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object datacenterID: description: The unique ID of the IONOS data center. minLength: 1 type: string enableHTTP2: description: Configure whether to enable HTTP2. type: boolean followRedirects: description: Configure whether the HTTP requests should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: Configure whether to enable OAuth2. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object port: description: Port to scrape the metrics from. format: int32 maximum: 65535 minimum: 0 type: integer proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: Refresh interval to re-read the list of resources. 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 tlsConfig: description: TLS configuration to use when connecting to the IONOS API. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - authorization - datacenterID type: object type: array jobName: description: |- The value of the `job` label assigned to the scraped metrics by default. The `job_name` field in the rendered scrape configuration is always controlled by the operator to prevent duplicate job names, which Prometheus does not allow. Instead the `job` label is set by means of relabeling configs. minLength: 1 type: string keepDroppedTargets: description: |- Per-scrape limit on the number of targets dropped by relabeling that will be kept in memory. 0 means no limit. It requires Prometheus >= v2.47.0. format: int64 type: integer kubernetesSDConfigs: description: KubernetesSDConfigs defines a list of Kubernetes service discovery configurations. items: description: |- KubernetesSDConfig allows retrieving scrape targets from Kubernetes' REST API. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config properties: apiServer: description: |- The API server address consisting of a hostname or IP address followed by an optional port number. If left empty, Prometheus is assumed to run inside of the cluster. It will discover API servers automatically and use the pod's CA certificate and bearer token file at /var/run/secrets/kubernetes.io/serviceaccount/. minLength: 1 type: string attachMetadata: description: |- Optional metadata to attach to discovered targets. It requires Prometheus >= v2.35.0 when using the `Pod` role and Prometheus >= v2.37.0 for `Endpoints` and `Endpointslice` roles. properties: node: description: |- Attaches node metadata to discovered targets. When set to true, Prometheus must have the `get` permission on the `Nodes` objects. Only valid for Pod, Endpoint and Endpointslice roles. type: boolean type: object authorization: description: |- Authorization header to use on every scrape request. Cannot be set at the same time as `basicAuth`, or `oauth2`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- BasicAuth information to use on every scrape request. Cannot be set at the same time as `authorization`, or `oauth2`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object enableHTTP2: description: Whether to enable HTTP2. type: boolean followRedirects: description: Configure whether HTTP requests follow HTTP 3xx redirects. type: boolean namespaces: description: Optional namespace discovery. If omitted, Prometheus discovers targets across all namespaces. properties: names: description: |- List of namespaces where to watch for resources. If empty and `ownNamespace` isn't true, Prometheus watches for resources in all namespaces. items: type: string type: array x-kubernetes-list-type: set ownNamespace: description: Includes the namespace in which the Prometheus pod runs to the list of watched namespaces. type: boolean type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- Optional OAuth 2.0 configuration. Cannot be set at the same time as `authorization`, or `basicAuth`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string role: description: |- Role of the Kubernetes entities that should be discovered. Role `Endpointslice` requires Prometheus >= v2.21.0 enum: - Pod - Endpoints - Ingress - Service - Node - EndpointSlice type: string selectors: description: |- Selector to select objects. It requires Prometheus >= v2.17.0 items: description: K8SSelectorConfig is Kubernetes Selector Config properties: field: description: |- An optional field selector to limit the service discovery to resources which have fields with specific values. e.g: `metadata.name=foobar` minLength: 1 type: string label: description: |- An optional label selector to limit the service discovery to resources with specific labels and label values. e.g: `node.kubernetes.io/instance-type=master` minLength: 1 type: string role: description: |- Role specifies the type of Kubernetes resource to limit the service discovery to. Accepted values are: Node, Pod, Endpoints, EndpointSlice, Service, Ingress. enum: - Pod - Endpoints - Ingress - Service - Node - EndpointSlice type: string required: - role type: object type: array x-kubernetes-list-map-keys: - role x-kubernetes-list-type: map tlsConfig: description: TLS configuration to connect to the Kubernetes API. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - role type: object type: array kumaSDConfigs: description: KumaSDConfigs defines a list of Kuma service discovery configurations. items: description: |- KumaSDConfig allow retrieving scrape targets from Kuma's control plane. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kuma_sd_config properties: authorization: description: Authorization header to use on every scrape request. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: BasicAuth information to use on every scrape request. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientID: description: Client id is used by Kuma Control Plane to compute Monitoring Assignment for specific Prometheus backend. type: string enableHTTP2: description: Whether to enable HTTP2. type: boolean fetchTimeout: description: The time after which the monitoring assignments are refreshed. 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 followRedirects: description: Configure whether HTTP requests follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- Optional OAuth 2.0 configuration. Cannot be set at the same time as `authorization`, or `basicAuth`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: The time to wait between polling update requests. 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 server: description: Address of the Kuma Control Plane's MADS xDS server. minLength: 1 type: string tlsConfig: description: TLS configuration to use on every scrape request 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - server type: object type: array 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 lightSailSDConfigs: description: LightsailSDConfigs defines a list of Lightsail service discovery configurations. items: description: |- LightSailSDConfig configurations allow retrieving scrape targets from AWS Lightsail instances. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#lightsail_sd_config properties: accessKey: description: AccessKey is the AWS API key. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic authorization: description: |- Optional `authorization` HTTP header configuration. Cannot be set at the same time as `basicAuth`, or `oauth2`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- Optional HTTP basic authentication information. Cannot be set at the same time as `authorization`, or `oauth2`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object enableHTTP2: description: Configure whether to enable HTTP2. type: boolean endpoint: description: Custom endpoint to be used. minLength: 1 type: string followRedirects: description: Configure whether the HTTP requests should follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- Optional OAuth2.0 configuration. Cannot be set at the same time as `basicAuth`, or `authorization`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object port: description: |- Port to scrape the metrics from. If using the public IP address, this must instead be specified in the relabeling rule. format: int32 maximum: 65535 minimum: 0 type: integer proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: Refresh interval to re-read the list of instances. 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 region: description: The AWS region. minLength: 1 type: string roleARN: description: AWS Role ARN, an alternative to using AWS API keys. type: string secretKey: description: SecretKey is the AWS API secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic tlsConfig: description: TLS configuration to connect to the Puppet DB. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object type: array linodeSDConfigs: description: LinodeSDConfigs defines a list of Linode service discovery configurations. items: description: |- LinodeSDConfig configurations allow retrieving scrape targets from Linode's Linode APIv4. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#linode_sd_config properties: authorization: description: Authorization header configuration. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object enableHTTP2: description: Whether to enable HTTP2. type: boolean followRedirects: description: Configure whether HTTP requests follow HTTP 3xx redirects. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- Optional OAuth 2.0 configuration. Cannot be used at the same time as `authorization`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object port: description: Default port to scrape metrics from. format: int32 maximum: 65535 minimum: 0 type: integer proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: Time after which the linode instances are refreshed. 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 region: description: Optional region to filter on. minLength: 1 type: string tagSeparator: description: The string by which Linode Instance tags are joined into the tag label. minLength: 1 type: string tlsConfig: description: TLS configuration applying to the target HTTP 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object type: object type: array 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. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. Regex capture groups are available. type: string type: object minItems: 1 type: array metricsPath: description: MetricsPath HTTP path to scrape for metrics. If empty, Prometheus uses the default value (e.g. /metrics). minLength: 1 type: string nameEscapingScheme: description: |- Metric name escaping mode to request through content negotiation. It requires Prometheus >= v3.4.0. enum: - AllowUTF8 - Underscores - Dots - Values type: string nameValidationScheme: description: |- Specifies the validation scheme for metric and label names. It requires Prometheus >= v3.0.0. enum: - UTF8 - Legacy type: string nativeHistogramBucketLimit: description: |- If there are more than this many buckets in a native histogram, buckets will be merged to stay within the limit. It requires Prometheus >= v2.45.0. format: int64 type: integer nativeHistogramMinBucketFactor: anyOf: - type: integer - type: string description: |- If the growth factor of one bucket to the next is smaller than this, buckets will be merged to increase the factor sufficiently. It requires Prometheus >= v2.50.0. pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string nomadSDConfigs: description: NomadSDConfigs defines a list of Nomad service discovery configurations. items: description: |- NomadSDConfig configurations allow retrieving scrape targets from Nomad's Service API. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#nomad_sd_config properties: allowStale: description: |- The information to access the Nomad API. It is to be defined as the Nomad documentation requires. type: boolean authorization: description: Authorization header to use on every scrape request. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: BasicAuth information to use on every scrape request. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object enableHTTP2: description: Whether to enable HTTP2. type: boolean followRedirects: description: Configure whether HTTP requests follow HTTP 3xx redirects. type: boolean namespace: type: string noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- Optional OAuth 2.0 configuration. Cannot be set at the same time as `authorization` or `basic_auth`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: |- Duration is a valid time duration that can be parsed by Prometheus model.ParseDuration() function. Supported units: y, w, d, h, m, s, ms Examples: `30s`, `1m`, `1h20m15s`, `15d` 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 region: type: string server: minLength: 1 type: string tagSeparator: type: string tlsConfig: description: TLS configuration applying to the target HTTP 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object required: - server type: object type: array oauth2: description: OAuth2 configuration to use on every scrape request. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object openstackSDConfigs: description: OpenStackSDConfigs defines a list of OpenStack service discovery configurations. items: description: |- OpenStackSDConfig allow retrieving scrape targets from OpenStack Nova instances. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#openstack_sd_config properties: allTenants: description: |- Whether the service discovery should list all instances for all projects. It is only relevant for the 'instance' role and usually requires admin permissions. type: boolean applicationCredentialId: description: ApplicationCredentialID type: string applicationCredentialName: description: |- The ApplicationCredentialID or ApplicationCredentialName fields are required if using an application credential to authenticate. Some providers allow you to create an application credential to authenticate rather than a password. minLength: 1 type: string applicationCredentialSecret: description: |- The applicationCredentialSecret field is required if using an application credential to authenticate. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic availability: description: Availability of the endpoint to connect to. enum: - Public - public - Admin - admin - Internal - internal type: string domainID: description: DomainID minLength: 1 type: string domainName: description: |- At most one of domainId and domainName must be provided if using username with Identity V3. Otherwise, either are optional. minLength: 1 type: string identityEndpoint: description: |- IdentityEndpoint specifies the HTTP endpoint that is required to work with the Identity API of the appropriate version. pattern: ^http(s)?:\/\/.+$ type: string password: description: |- Password for the Identity V2 and V3 APIs. Consult with your provider's control panel to discover your account's preferred method of authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic port: description: |- The port to scrape metrics from. If using the public IP address, this must instead be specified in the relabeling rule. format: int32 maximum: 65535 minimum: 0 type: integer projectID: description: ' ProjectID' minLength: 1 type: string projectName: description: |- The ProjectId and ProjectName fields are optional for the Identity V2 API. Some providers allow you to specify a ProjectName instead of the ProjectId. Some require both. Your provider's authentication policies will determine how these fields influence authentication. minLength: 1 type: string refreshInterval: description: Refresh interval to re-read the instance list. 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 region: description: The OpenStack Region. minLength: 1 type: string role: description: |- The OpenStack role of entities that should be discovered. Note: The `LoadBalancer` role requires Prometheus >= v3.2.0. enum: - Instance - Hypervisor - LoadBalancer type: string tlsConfig: description: TLS configuration applying to the target HTTP 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object userid: description: UserID minLength: 1 type: string username: description: |- Username is required if using Identity V2 API. Consult with your provider's control panel to discover your account's username. In Identity V3, either userid or a combination of username and domainId or domainName are needed minLength: 1 type: string required: - region - role type: object type: array ovhcloudSDConfigs: description: OVHCloudSDConfigs defines a list of OVHcloud service discovery configurations. items: description: |- OVHCloudSDConfig configurations allow retrieving scrape targets from OVHcloud's dedicated servers and VPS using their API. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#ovhcloud_sd_config properties: applicationKey: description: Access key to use. https://api.ovh.com. minLength: 1 type: string applicationSecret: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic consumerKey: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpoint: description: Custom endpoint to be used. minLength: 1 type: string refreshInterval: description: Refresh interval to re-read the resources list. 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 service: allOf: - enum: - VPS - DedicatedServer - enum: - VPS - DedicatedServer description: Service of the targets to retrieve. Must be `VPS` or `DedicatedServer`. type: string required: - applicationKey - applicationSecret - consumerKey - service type: object type: array params: additionalProperties: items: type: string type: array description: Optional HTTP URL parameters type: object x-kubernetes-map-type: atomic proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string puppetDBSDConfigs: description: PuppetDBSDConfigs defines a list of PuppetDB service discovery configurations. items: description: |- PuppetDBSDConfig configurations allow retrieving scrape targets from PuppetDB resources. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#puppetdb_sd_config properties: authorization: description: |- Optional `authorization` HTTP header configuration. Cannot be set at the same time as `basicAuth`, or `oauth2`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- Optional HTTP basic authentication information. Cannot be set at the same time as `authorization`, or `oauth2`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object enableHTTP2: description: Configure whether to enable HTTP2. type: boolean followRedirects: description: Configure whether the HTTP requests should follow HTTP 3xx redirects. type: boolean includeParameters: description: |- Whether to include the parameters as meta labels. Note: Enabling this exposes parameters in the Prometheus UI and API. Make sure that you don't have secrets exposed as parameters if you enable this. type: boolean noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- Optional OAuth2.0 configuration. Cannot be set at the same time as `basicAuth`, or `authorization`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object port: description: Port to scrape the metrics from. format: int32 maximum: 65535 minimum: 0 type: integer proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string query: description: |- Puppet Query Language (PQL) query. Only resources are supported. https://puppet.com/docs/puppetdb/latest/api/query/v4/pql.html minLength: 1 type: string refreshInterval: description: Refresh interval to re-read the list of resources. 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 tlsConfig: description: TLS configuration to connect to the Puppet DB. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object url: description: The URL of the PuppetDB root query endpoint. minLength: 1 pattern: ^http(s)?://.+$ type: string required: - query - url type: object type: array relabelings: description: |- RelabelConfigs defines how to rewrite the target's labels 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. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. Regex capture groups are available. type: string type: object minItems: 1 type: array sampleLimit: description: SampleLimit defines per-scrape limit on number of scraped samples that will be accepted. format: int64 type: integer scalewaySDConfigs: description: ScalewaySDConfigs defines a list of Scaleway instances and baremetal service discovery configurations. items: description: |- ScalewaySDConfig configurations allow retrieving scrape targets from Scaleway instances and baremetal services. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scaleway_sd_config properties: accessKey: description: Access key to use. https://console.scaleway.com/project/credentials minLength: 1 type: string apiURL: description: API URL to use when doing the server listing requests. pattern: ^http(s)?://.+$ type: string enableHTTP2: description: Whether to enable HTTP2. type: boolean followRedirects: description: Configure whether HTTP requests follow HTTP 3xx redirects. type: boolean nameFilter: description: NameFilter specify a name filter (works as a LIKE) to apply on the server listing request. minLength: 1 type: string noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string port: description: The port to scrape metrics from. format: int32 maximum: 65535 minimum: 0 type: integer projectID: description: Project ID of the targets. minLength: 1 type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string refreshInterval: description: Refresh interval to re-read the list of instances. 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 role: description: Service of the targets to retrieve. Must be `Instance` or `Baremetal`. enum: - Instance - Baremetal type: string secretKey: description: Secret key to use when listing targets. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic tagsFilter: description: TagsFilter specify a tag filter (a server needs to have all defined tags to be listed) to apply on the server listing request. items: minLength: 1 type: string minItems: 1 type: array x-kubernetes-list-type: set tlsConfig: description: TLS configuration to use on every scrape request 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object zone: description: Zone is the availability zone of your targets (e.g. fr-par-1). minLength: 1 type: string required: - accessKey - projectID - role - secretKey type: object type: array scheme: description: |- Configures the protocol scheme used for requests. If empty, Prometheus uses HTTP by default. enum: - HTTP - HTTPS type: string scrapeClass: description: The scrape class to apply. minLength: 1 type: string scrapeClassicHistograms: description: |- Whether to scrape a classic histogram that is also exposed as a native histogram. It requires Prometheus >= v2.45.0. Notice: `scrapeClassicHistograms` corresponds to the `always_scrape_classic_histograms` field in the Prometheus configuration. type: boolean scrapeInterval: description: ScrapeInterval is the interval between consecutive scrapes. 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 scrapeProtocols: description: |- The protocols to negotiate during a scrape. It tells clients the protocols supported by Prometheus in order of preference (from most to least preferred). If unset, Prometheus uses its default value. It requires Prometheus >= v2.49.0. items: description: |- ScrapeProtocol represents a protocol used by Prometheus for scraping metrics. Supported values are: * `OpenMetricsText0.0.1` * `OpenMetricsText1.0.0` * `PrometheusProto` * `PrometheusText0.0.4` * `PrometheusText1.0.0` enum: - PrometheusProto - OpenMetricsText0.0.1 - OpenMetricsText1.0.0 - PrometheusText0.0.4 - PrometheusText1.0.0 type: string minItems: 1 type: array x-kubernetes-list-type: set scrapeTimeout: description: |- ScrapeTimeout is the number of seconds to wait until a scrape request times out. The value cannot be greater than the scrape interval otherwise the operator will reject the resource. 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 staticConfigs: description: StaticConfigs defines a list of static targets with a common label set. items: description: |- StaticConfig defines a Prometheus static configuration. See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config properties: labels: additionalProperties: type: string description: Labels assigned to all metrics scraped from the targets. type: object x-kubernetes-map-type: atomic targets: description: List of targets for this static configuration. items: description: |- Target represents a target for Prometheus to scrape kubebuilder:validation:MinLength:=1 type: string minItems: 1 type: array x-kubernetes-list-type: set required: - targets type: object type: array targetLimit: description: TargetLimit defines a limit on the number of scraped targets that will be accepted. format: int64 type: integer tlsConfig: description: TLS configuration to use on every scrape request 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object trackTimestampsStaleness: description: |- TrackTimestampsStaleness whether Prometheus tracks staleness of the metrics that have an explicit timestamp present in scraped data. Has no effect if `honorTimestamps` is false. It requires Prometheus >= v2.48.0. type: boolean type: object required: - spec type: object served: true storage: true ================================================ FILE: hack/config/monitoring/crds/0servicemonitorCustomResourceDefinition.yaml ================================================ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 operator.prometheus.io/version: 0.85.0 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: |- The `ServiceMonitor` custom resource definition (CRD) defines how `Prometheus` and `PrometheusAgent` can scrape metrics from a group of services. Among other things, it allows to specify: * The services to scrape via label selectors. * The container ports to scrape. * Authentication credentials to use. * Target and metric relabeling. `Prometheus` and `PrometheusAgent` objects select `ServiceMonitor` objects using label and namespace 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: |- Specification of desired Service selection for target discovery by Prometheus. properties: attachMetadata: description: |- `attachMetadata` defines additional metadata which is added to the discovered targets. It requires Prometheus >= v2.37.0. properties: node: description: |- When set to true, Prometheus attaches node metadata to the discovered targets. The Prometheus service account must have the `list` and `watch` permissions on the `Nodes` objects. type: boolean type: object bodySizeLimit: description: |- When defined, bodySizeLimit specifies a job level limit on the size of uncompressed response body that will be accepted by Prometheus. It requires Prometheus >= v2.28.0. pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$ type: string convertClassicHistogramsToNHCB: description: |- Whether to convert all scraped classic histograms into a native histogram with custom buckets. It requires Prometheus >= v3.0.0. type: boolean endpoints: description: |- List of endpoints part of this ServiceMonitor. Defines how to scrape metrics from Kubernetes [Endpoints](https://kubernetes.io/docs/concepts/services-networking/service/#endpoints) objects. In most cases, an Endpoints object is backed by a Kubernetes [Service](https://kubernetes.io/docs/concepts/services-networking/service/) object with the same name and labels. items: description: |- Endpoint defines an endpoint serving Prometheus metrics to be scraped by Prometheus. properties: authorization: description: |- `authorization` configures the Authorization header credentials to use when scraping the target. Cannot be set at the same time as `basicAuth`, or `oauth2`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object basicAuth: description: |- `basicAuth` configures the Basic Authentication credentials to use when scraping the target. Cannot be set at the same time as `authorization`, or `oauth2`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerTokenFile: description: |- File to read bearer token for scraping the target. Deprecated: use `authorization` instead. type: string bearerTokenSecret: description: |- `bearerTokenSecret` specifies a key of a Secret containing the bearer token for scraping targets. The secret needs to be in the same namespace as the ServiceMonitor object and readable by the Prometheus Operator. Deprecated: use `authorization` instead. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic enableHttp2: description: '`enableHttp2` can be used to disable HTTP2 when scraping the target.' type: boolean filterRunning: description: |- When true, the pods which are not running (e.g. either in Failed or Succeeded state) are dropped during the target discovery. If unset, the filtering is enabled. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase type: boolean followRedirects: description: |- `followRedirects` defines whether the scrape requests should follow HTTP 3xx redirects. type: boolean honorLabels: description: |- When true, `honorLabels` preserves the metric's labels when they collide with the target's labels. type: boolean honorTimestamps: description: |- `honorTimestamps` controls whether Prometheus preserves the timestamps when exposed by the target. type: boolean interval: description: |- Interval at which Prometheus scrapes the metrics from the target. If empty, Prometheus uses the global scrape interval. 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: |- `metricRelabelings` configures the relabeling rules to apply to the samples before ingestion. items: description: |- RelabelConfig allows dynamic rewriting of the label set for targets, alerts, scraped samples and remote write samples. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. Regex capture groups are available. type: string type: object type: array noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- `oauth2` configures the OAuth2 settings to use when scraping the target. It requires Prometheus >= 2.27.0. Cannot be set at the same time as `authorization`, or `basicAuth`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures 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: params define optional HTTP URL parameters. type: object path: description: |- HTTP path from which to scrape for metrics. If empty, Prometheus uses the default value (e.g. `/metrics`). type: string port: description: |- Name of the Service port which this endpoint refers to. It takes precedence over `targetPort`. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string relabelings: description: |- `relabelings` configures the relabeling rules to apply the target's metadata labels. The 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. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. 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 Prometheus considers the scrape to be failed. If empty, Prometheus uses the global scrape timeout unless it is less than the target's scrape interval value in which the latter is used. The value cannot be greater than the scrape interval otherwise the operator will reject the resource. 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` object behind the Service. The port must be specified with the container's port property. x-kubernetes-int-or-string: true tlsConfig: description: TLS configuration to use when scraping the target. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object trackTimestampsStaleness: description: |- `trackTimestampsStaleness` defines whether Prometheus tracks staleness of the metrics that have an explicit timestamp present in scraped data. Has no effect if `honorTimestamps` is false. It requires Prometheus >= v2.48.0. type: boolean type: object type: array fallbackScrapeProtocol: description: |- The protocol to use if a scrape returns blank, unparseable, or otherwise invalid Content-Type. It requires Prometheus >= v3.0.0. enum: - PrometheusProto - OpenMetricsText0.0.1 - OpenMetricsText1.0.0 - PrometheusText0.0.4 - PrometheusText1.0.0 type: string jobLabel: description: |- `jobLabel` selects the label from the associated Kubernetes `Service` object which will be used as the `job` label for all metrics. For example if `jobLabel` is set to `foo` and the Kubernetes `Service` object is labeled with `foo: bar`, then Prometheus adds the `job="bar"` label to all ingested metrics. 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 associated Kubernetes `Service`. type: string keepDroppedTargets: description: |- Per-scrape limit on the number of targets dropped by relabeling that will be kept in memory. 0 means no limit. It requires Prometheus >= v2.47.0. format: int64 type: integer labelLimit: description: |- Per-scrape limit on number of labels that will be accepted for a sample. It requires Prometheus >= v2.27.0. format: int64 type: integer labelNameLengthLimit: description: |- Per-scrape limit on length of labels name that will be accepted for a sample. It requires Prometheus >= v2.27.0. format: int64 type: integer labelValueLengthLimit: description: |- Per-scrape limit on length of labels value that will be accepted for a sample. It requires Prometheus >= v2.27.0. format: int64 type: integer namespaceSelector: description: |- `namespaceSelector` defines in which namespace(s) Prometheus should discover the services. By default, the services are discovered in the same namespace as the `ServiceMonitor` object but it is possible to select pods across different/all 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 to select from. items: type: string type: array type: object nativeHistogramBucketLimit: description: |- If there are more than this many buckets in a native histogram, buckets will be merged to stay within the limit. It requires Prometheus >= v2.45.0. format: int64 type: integer nativeHistogramMinBucketFactor: anyOf: - type: integer - type: string description: |- If the growth factor of one bucket to the next is smaller than this, buckets will be merged to increase the factor sufficiently. It requires Prometheus >= v2.50.0. pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true podTargetLabels: description: |- `podTargetLabels` defines the labels which are transferred from the associated Kubernetes `Pod` object onto the ingested metrics. items: type: string type: array sampleLimit: description: |- `sampleLimit` defines a per-scrape limit on the number of scraped samples that will be accepted. format: int64 type: integer scrapeClass: description: The scrape class to apply. minLength: 1 type: string scrapeClassicHistograms: description: |- Whether to scrape a classic histogram that is also exposed as a native histogram. It requires Prometheus >= v2.45.0. Notice: `scrapeClassicHistograms` corresponds to the `always_scrape_classic_histograms` field in the Prometheus configuration. type: boolean scrapeProtocols: description: |- `scrapeProtocols` defines the protocols to negotiate during a scrape. It tells clients the protocols supported by Prometheus in order of preference (from most to least preferred). If unset, Prometheus uses its default value. It requires Prometheus >= v2.49.0. items: description: |- ScrapeProtocol represents a protocol used by Prometheus for scraping metrics. Supported values are: * `OpenMetricsText0.0.1` * `OpenMetricsText1.0.0` * `PrometheusProto` * `PrometheusText0.0.4` * `PrometheusText1.0.0` enum: - PrometheusProto - OpenMetricsText0.0.1 - OpenMetricsText1.0.0 - PrometheusText0.0.4 - PrometheusText1.0.0 type: string type: array x-kubernetes-list-type: set selector: description: Label selector to select the Kubernetes `Endpoints` objects to scrape metrics from. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic selectorMechanism: description: |- Mechanism used to select the endpoints to scrape. By default, the selection process relies on relabel configurations to filter the discovered targets. Alternatively, you can opt in for role selectors, which may offer better efficiency in large clusters. Which strategy is best for your use case needs to be carefully evaluated. It requires Prometheus >= v2.17.0. enum: - RelabelConfig - RoleSelector type: string targetLabels: description: |- `targetLabels` defines the labels which are transferred from the associated Kubernetes `Service` object onto the ingested 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 status: description: |- This Status subresource is under active development and is updated only when the "StatusForConfigurationResources" feature gate is enabled. Most recent observed status of the ServiceMonitor. Read-only. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status properties: bindings: description: The list of workload resources (Prometheus or PrometheusAgent) which select the configuration resource. items: description: WorkloadBinding is a link between a configuration resource and a workload resource. properties: conditions: description: The current state of the configuration resource when bound to the referenced Prometheus object. items: description: ConfigResourceCondition describes the status of configuration resources linked to Prometheus, PrometheusAgent, Alertmanager, or ThanosRuler. properties: lastTransitionTime: description: LastTransitionTime is the time of the last update to the current status property. format: date-time type: string message: description: Human-readable message indicating details for the condition's last transition. 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[].observedGeneration` is 9, the condition is out of date with respect to the current state of the object. format: int64 type: integer reason: description: Reason for the condition's last transition. type: string status: description: Status of the condition. minLength: 1 type: string type: description: |- Type of the condition being reported. Currently, only "Accepted" is supported. enum: - Accepted minLength: 1 type: string required: - lastTransitionTime - status - type type: object type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map group: description: The group of the referenced resource. enum: - monitoring.coreos.com type: string name: description: The name of the referenced object. minLength: 1 type: string namespace: description: The namespace of the referenced object. minLength: 1 type: string resource: description: The type of resource being referenced (e.g. Prometheus or PrometheusAgent). enum: - prometheuses - prometheusagents type: string required: - group - name - namespace - resource type: object type: array x-kubernetes-list-map-keys: - group - resource - name - namespace x-kubernetes-list-type: map type: object required: - spec type: object served: true storage: true subresources: status: {} ================================================ FILE: hack/config/monitoring/crds/0thanosrulerCustomResourceDefinition.yaml ================================================ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 operator.prometheus.io/version: 0.85.0 name: thanosrulers.monitoring.coreos.com spec: group: monitoring.coreos.com names: categories: - prometheus-operator kind: ThanosRuler listKind: ThanosRulerList plural: thanosrulers shortNames: - ruler singular: thanosruler scope: Namespaced versions: - additionalPrinterColumns: - description: The version of Thanos Ruler jsonPath: .spec.version name: Version type: string - description: The number of desired replicas jsonPath: .spec.replicas name: Replicas type: integer - description: The number of ready replicas jsonPath: .status.availableReplicas name: Ready type: integer - jsonPath: .status.conditions[?(@.type == 'Reconciled')].status name: Reconciled type: string - jsonPath: .status.conditions[?(@.type == 'Available')].status name: Available type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - description: Whether the resource reconciliation is paused or not jsonPath: .status.paused name: Paused priority: 1 type: boolean name: v1 schema: openAPIV3Schema: description: |- The `ThanosRuler` custom resource definition (CRD) defines a desired [Thanos Ruler](https://github.com/thanos-io/thanos/blob/main/docs/components/rule.md) setup to run in a Kubernetes cluster. A `ThanosRuler` instance requires at least one compatible Prometheus API endpoint (either Thanos Querier or Prometheus services). The resource defines via label and namespace selectors which `PrometheusRule` objects should be associated to the deployed Thanos Ruler instances. 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 ThanosRuler cluster. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status properties: additionalArgs: description: |- AdditionalArgs allows setting additional arguments for the ThanosRuler container. It is intended for e.g. activating hidden flags which are not supported by the dedicated configuration options yet. The arguments are passed as-is to the ThanosRuler container which may cause issues if they are invalid or not supported by the given ThanosRuler version. In case of an argument conflict (e.g. an argument which is already set by the operator itself) or when providing an invalid argument the reconciliation will fail and an error will be logged. items: description: Argument as part of the AdditionalArgs list. properties: name: description: Name of the argument, e.g. "scrape.discovery-reload-interval". minLength: 1 type: string value: description: Argument value, e.g. 30s. Can be empty for name-only arguments (e.g. --storage.tsdb.no-lockfile) type: string required: - name type: object type: array 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic type: array x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select 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. 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. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic type: object type: object alertDropLabels: description: |- Configures the label names which should be dropped in Thanos Ruler alerts. The replica label `thanos_ruler_replica` will always be dropped from the alerts. items: type: string type: array alertQueryUrl: description: |- The external Query URL the Thanos Ruler will set in the 'Source' field of all alerts. Maps to the '--alert.query-url' CLI arg. type: string alertRelabelConfigFile: description: |- Configures the path to the alert relabeling configuration file. Alert relabel configuration must have the form as specified in the official Prometheus documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alert_relabel_configs The operator performs no validation of the configuration file. This field takes precedence over `alertRelabelConfig`. type: string alertRelabelConfigs: description: |- Configures alert relabeling in Thanos Ruler. Alert relabel configuration must have the form as specified in the official Prometheus documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alert_relabel_configs The operator performs no validation of the configuration. `alertRelabelConfigFile` takes precedence over this field. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic alertmanagersConfig: description: |- Configures the list of Alertmanager endpoints to send alerts to. The configuration format is defined at https://thanos.io/tip/components/rule.md/#alertmanager. It requires Thanos >= v0.10.0. The operator performs no validation of the configuration. This field takes precedence over `alertmanagersUrl`. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic alertmanagersUrl: description: |- Configures the list of Alertmanager endpoints to send alerts to. For Thanos >= v0.10.0, it is recommended to use `alertmanagersConfig` instead. `alertmanagersConfig` takes precedence over this field. items: type: string type: array containers: description: |- Containers allows injecting additional containers or modifying operator generated containers. This can be used to allow adding an authentication proxy to a ThanosRuler pod or to change the behavior of an operator generated container. Containers described here modify an operator generated container if they share the same name and modifications are done via a strategic merge patch. The current container names are: `thanos-ruler` and `config-reloader`. Overriding containers 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. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: description: |- Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string description: Specifies the output format of the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: description: Selects a key of a secret in the pod's namespace properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map 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 or Secrets properties: configMapRef: description: The ConfigMap to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret must be defined type: boolean type: object x-kubernetes-map-type: atomic type: object type: array x-kubernetes-list-type: atomic 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 stopSignal: description: |- StopSignal defines which signal will be sent to a container when it is being stopped. If not specified, the default is defined by the container runtime in use. StopSignal can only be set for Pods with a non-empty .spec.os.name type: string 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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. This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: description: |- Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. type: string request: description: |- Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object 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 appArmorProfile: description: |- appArmorProfile is the AppArmor options to use by this container. If set, this profile overrides the pod's appArmorProfile. Note that this field cannot be set when spec.os.name is windows. properties: localhostProfile: description: |- localhostProfile indicates a profile loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost". type: string type: description: |- type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement. type: string required: - type type: object 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 x-kubernetes-list-type: atomic drop: description: Removed capabilities items: description: Capability represent POSIX capabilities type type: string type: array x-kubernetes-list-type: atomic 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 value is Default 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: 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 x-kubernetes-list-map-keys: - devicePath x-kubernetes-list-type: map 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. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None). 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 recursiveReadOnly: description: |- RecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled. type: string 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 x-kubernetes-list-map-keys: - mountPath x-kubernetes-list-type: map 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: Defines the DNS configuration for the pods. properties: nameservers: description: |- A list of DNS name server IP addresses. This will be appended to the base nameservers generated from DNSPolicy. items: minLength: 1 type: string type: array x-kubernetes-list-type: set options: description: |- A list of DNS resolver options. This will be merged with the base options generated from DNSPolicy. 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: Name is required and must be unique. minLength: 1 type: string value: description: Value is optional. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map searches: description: |- A list of DNS search domains for host-name lookup. This will be appended to the base search paths generated from DNSPolicy. items: minLength: 1 type: string type: array x-kubernetes-list-type: set type: object dnsPolicy: description: Defines the DNS policy for the pods. enum: - ClusterFirstWithHostNet - ClusterFirst - Default - None type: string enableFeatures: description: |- Enable access to Thanos Ruler feature flags. By default, no features are enabled. Enabling features which are disabled by default 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. For more information see https://thanos.io/tip/components/rule.md/ It requires Thanos >= 0.39.0. items: minLength: 1 type: string type: array x-kubernetes-list-type: set enableServiceLinks: description: Indicates whether information about services should be injected into pod's environment variables type: boolean 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: default: 15s description: Interval between consecutive evaluations. 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 excludedFromEnforcement: description: |- List of references to PrometheusRule objects to be excluded from enforcing a namespace label of origin. Applies only if enforcedNamespaceLabel set to true. items: description: ObjectReference references a PodMonitor, ServiceMonitor, Probe or PrometheusRule object. properties: group: default: monitoring.coreos.com description: Group of the referent. When not specified, it defaults to `monitoring.coreos.com` enum: - monitoring.coreos.com type: string name: description: Name of the referent. When not set, all resources in the namespace are matched. type: string namespace: description: |- Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ minLength: 1 type: string resource: description: Resource of the referent. enum: - prometheusrules - servicemonitors - podmonitors - probes - scrapeconfigs type: string required: - namespace - resource type: object type: array externalPrefix: description: |- The external URL the Thanos Ruler instances will be available under. This is necessary to generate correct URLs. This is necessary if Thanos Ruler is not served from root of a DNS name. type: string grpcServerTlsConfig: description: |- GRPCServerTLSConfig configures the gRPC server from which Thanos Querier reads recorded rule data. Note: Currently only the CAFile, CertFile, and KeyFile fields are supported. Maps to the '--grpc-server-tls-*' CLI args. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object hostAliases: description: Pods' hostAliases configuration 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 required: - hostnames - ip type: object type: array x-kubernetes-list-map-keys: - ip x-kubernetes-list-type: map hostUsers: description: |- HostUsers supports the user space in Kubernetes. More info: https://kubernetes.io/docs/tasks/configure-pod-container/user-namespaces/ The feature requires at least Kubernetes 1.28 with the `UserNamespacesSupport` feature gate enabled. Starting Kubernetes 1.33, the feature is enabled by default. type: boolean image: description: Thanos container image URL. type: string imagePullPolicy: description: |- Image pull policy for the 'thanos', 'init-config-reloader' and 'config-reloader' containers. See https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy for more details. enum: - "" - Always - Never - IfNotPresent type: string imagePullSecrets: description: |- An optional list of references to secrets in the same namespace to use for pulling thanos images from registries see http://kubernetes.io/docs/user-guide/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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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 ThanosRuler 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. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic fieldRef: description: |- Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. properties: apiVersion: description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string fieldPath: description: Path of the field to select in the specified API version. type: string required: - fieldPath type: object x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. properties: containerName: description: 'Container name: required for volumes, optional for env vars' type: string divisor: anyOf: - type: integer - type: string description: Specifies the output format of the exposed resources, defaults to "1" pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true resource: description: 'Required: resource to select' type: string required: - resource type: object x-kubernetes-map-type: atomic secretKeyRef: description: Selects a key of a secret in the pod's namespace properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map 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 or Secrets properties: configMapRef: description: The ConfigMap to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap must be defined type: boolean type: object x-kubernetes-map-type: atomic prefix: description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from properties: name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret must be defined type: boolean type: object x-kubernetes-map-type: atomic type: object type: array x-kubernetes-list-type: atomic 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a duration that the container should sleep. 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 backward compatibility. There is no validation of this field and lifecycle hooks will fail at runtime when it 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 stopSignal: description: |- StopSignal defines which signal will be sent to a container when it is being stopped. If not specified, the default is defined by the container runtime in use. StopSignal can only be set for Pods with a non-empty .spec.os.name type: string 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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. This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: description: |- Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. type: string request: description: |- Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object 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 appArmorProfile: description: |- appArmorProfile is the AppArmor options to use by this container. If set, this profile overrides the pod's appArmorProfile. Note that this field cannot be set when spec.os.name is windows. properties: localhostProfile: description: |- localhostProfile indicates a profile loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost". type: string type: description: |- type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement. type: string required: - type type: object 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 x-kubernetes-list-type: atomic drop: description: Removed capabilities items: description: Capability represent POSIX capabilities type type: string type: array x-kubernetes-list-type: atomic 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 value is Default 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: 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 a command to execute in the container. 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 x-kubernetes-list-type: atomic 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 a GRPC HealthCheckRequest. properties: port: description: Port number of the gRPC service. Number must be in the range 1 to 65535. format: int32 type: integer service: default: "" 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). If this is not specified, the default behavior is defined by gRPC. type: string required: - port type: object httpGet: description: HTTPGet specifies an HTTP GET 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 x-kubernetes-list-type: atomic 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 a connection to 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 x-kubernetes-list-map-keys: - devicePath x-kubernetes-list-type: map 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. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None). 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 recursiveReadOnly: description: |- RecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled. type: string 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 x-kubernetes-list-map-keys: - mountPath x-kubernetes-list-type: map 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 labels: additionalProperties: type: string description: |- Configures the external label pairs of the ThanosRuler resource. A default replica label `thanos_ruler_replica` will be always added as a label with the value of the pod's name. type: object listenLocal: description: |- ListenLocal makes the Thanos ruler listen on loopback, so that it does not bind against the Pod IP. type: boolean logFormat: description: Log format for ThanosRuler to be configured with. enum: - "" - logfmt - json type: string logLevel: description: Log level for ThanosRuler to be configured with. enum: - "" - debug - info - warn - error type: string minReadySeconds: description: |- Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to be considered available. If unset, pods will be considered available as soon as they are ready. format: int32 minimum: 0 type: integer nodeSelector: additionalProperties: type: string description: Define which Nodes the Pods are scheduled on. type: object objectStorageConfig: description: |- Configures object storage. The configuration format is defined at https://thanos.io/tip/thanos/storage.md/#configuring-access-to-object-storage The operator performs no validation of the configuration. `objectStorageConfigFile` takes precedence over this field. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic objectStorageConfigFile: description: |- Configures the path of the object storage configuration file. The configuration format is defined at https://thanos.io/tip/thanos/storage.md/#configuring-access-to-object-storage The operator performs no validation of the configuration file. This field takes precedence over `objectStorageConfig`. type: string paused: description: |- When a ThanosRuler deployment is paused, no actions except for deletion will be performed on the underlying objects. type: boolean podMetadata: description: |- PodMetadata configures labels and annotations which are propagated to the ThanosRuler pods. The following items are reserved and cannot be overridden: * "app.kubernetes.io/name" label, set to "thanos-ruler". * "app.kubernetes.io/managed-by" label, set to "prometheus-operator". * "app.kubernetes.io/instance" label, set to the name of the ThanosRuler instance. * "thanos-ruler" label, set to the name of the ThanosRuler instance. * "kubectl.kubernetes.io/default-container" annotation, set to "thanos-ruler". 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. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/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: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/ type: string type: object portName: default: web description: |- Port name used for the pods and governing service. Defaults to `web`. type: string priorityClassName: description: Priority class assigned to the Pods type: string prometheusRulesExcludedFromEnforce: description: |- PrometheusRulesExcludedFromEnforce - list of Prometheus rules to be excluded from enforcing of adding namespace labels. Works only if enforcedNamespaceLabel set to true. Make sure both ruleNamespace and ruleName are set for each pair Deprecated: use excludedFromEnforcement instead. items: description: |- PrometheusRuleExcludeConfig enables users to configure excluded PrometheusRule names and their namespaces to be ignored while enforcing namespace label for alerts and metrics. properties: ruleName: description: Name of the excluded PrometheusRule object. type: string ruleNamespace: description: Namespace of the excluded PrometheusRule object. type: string required: - ruleName - ruleNamespace type: object type: array queryConfig: description: |- Configures the list of Thanos Query endpoints from which to query metrics. The configuration format is defined at https://thanos.io/tip/components/rule.md/#query-api It requires Thanos >= v0.11.0. The operator performs no validation of the configuration. This field takes precedence over `queryEndpoints`. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic queryEndpoints: description: |- Configures the list of Thanos Query endpoints from which to query metrics. For Thanos >= v0.11.0, it is recommended to use `queryConfig` instead. `queryConfig` takes precedence over this field. items: type: string type: array remoteWrite: description: |- Defines the list of remote write configurations. When the list isn't empty, the ruler is configured with stateless mode. It requires Thanos >= 0.24.0. items: description: |- RemoteWriteSpec defines the configuration to write samples from Prometheus to a remote endpoint. properties: authorization: description: |- Authorization section for the URL. It requires Prometheus >= v2.26.0 or Thanos >= v0.24.0. Cannot be set at the same time as `sigv4`, `basicAuth`, `oauth2`, or `azureAd`. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic credentialsFile: description: File to read a secret from, mutually exclusive with `credentials`. type: string type: description: |- Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer" type: string type: object azureAd: description: |- AzureAD for the URL. It requires Prometheus >= v2.45.0 or Thanos >= v0.31.0. Cannot be set at the same time as `authorization`, `basicAuth`, `oauth2`, or `sigv4`. properties: cloud: description: The Azure Cloud. Options are 'AzurePublic', 'AzureChina', or 'AzureGovernment'. enum: - AzureChina - AzureGovernment - AzurePublic type: string managedIdentity: description: |- ManagedIdentity defines the Azure User-assigned Managed identity. Cannot be set at the same time as `oauth` or `sdk`. properties: clientId: description: The client id type: string required: - clientId type: object oauth: description: |- OAuth defines the oauth config that is being used to authenticate. Cannot be set at the same time as `managedIdentity` or `sdk`. It requires Prometheus >= v2.48.0 or Thanos >= v0.31.0. properties: clientId: description: '`clientID` is the clientId of the Azure Active Directory application that is being used to authenticate.' minLength: 1 type: string clientSecret: description: '`clientSecret` specifies a key of a Secret containing the client secret of the Azure Active Directory application that is being used to authenticate.' properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic tenantId: description: '`tenantId` is the tenant ID of the Azure Active Directory application that is being used to authenticate.' minLength: 1 pattern: ^[0-9a-zA-Z-.]+$ type: string required: - clientId - clientSecret - tenantId type: object sdk: description: |- SDK defines the Azure SDK config that is being used to authenticate. See https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication Cannot be set at the same time as `oauth` or `managedIdentity`. It requires Prometheus >= v2.52.0 or Thanos >= v0.36.0. properties: tenantId: description: '`tenantId` is the tenant ID of the azure active directory application that is being used to authenticate.' pattern: ^[0-9a-zA-Z-.]+$ type: string type: object type: object basicAuth: description: |- BasicAuth configuration for the URL. Cannot be set at the same time as `sigv4`, `authorization`, `oauth2`, or `azureAd`. properties: password: description: |- `password` specifies a key of a Secret containing the password for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic username: description: |- `username` specifies a key of a Secret containing the username for authentication. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object bearerToken: description: |- *Warning: this field shouldn't be used because the token value appears in clear-text. Prefer using `authorization`.* Deprecated: this will be removed in a future release. type: string bearerTokenFile: description: |- File from which to read bearer token for the URL. Deprecated: this will be removed in a future release. Prefer using `authorization`. type: string enableHTTP2: description: Whether to enable HTTP2. type: boolean followRedirects: description: |- Configure whether HTTP requests follow HTTP 3xx redirects. It requires Prometheus >= v2.26.0 or Thanos >= v0.24.0. type: boolean headers: additionalProperties: type: string description: |- Custom HTTP headers to be sent along with each remote write request. Be aware that headers that are set by Prometheus itself can't be overwritten. It requires Prometheus >= v2.25.0 or Thanos >= v0.24.0. type: object messageVersion: description: |- The Remote Write message's version to use when writing to the endpoint. `Version1.0` corresponds to the `prometheus.WriteRequest` protobuf message introduced in Remote Write 1.0. `Version2.0` corresponds to the `io.prometheus.write.v2.Request` protobuf message introduced in Remote Write 2.0. When `Version2.0` is selected, Prometheus will automatically be configured to append the metadata of scraped metrics to the WAL. Before setting this field, consult with your remote storage provider what message version it supports. It requires Prometheus >= v2.54.0 or Thanos >= v0.37.0. enum: - V1.0 - V2.0 type: string metadataConfig: description: MetadataConfig configures the sending of series metadata to the remote storage. properties: maxSamplesPerSend: description: |- MaxSamplesPerSend is the maximum number of metadata samples per send. It requires Prometheus >= v2.29.0. format: int32 minimum: -1 type: integer send: description: Defines whether metric metadata is sent to the remote storage or not. type: boolean sendInterval: description: Defines how frequently metric metadata is sent to the remote storage. 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 type: object name: description: |- The name of the remote write queue, it must be unique if specified. The name is used in metrics and logging in order to differentiate queues. It requires Prometheus >= v2.15.0 or Thanos >= 0.24.0. type: string noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string oauth2: description: |- OAuth2 configuration for the URL. It requires Prometheus >= v2.27.0 or Thanos >= v0.24.0. Cannot be set at the same time as `sigv4`, `authorization`, `basicAuth`, or `azureAd`. properties: clientId: description: |- `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientSecret: description: |- `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic endpointParams: additionalProperties: type: string description: |- `endpointParams` configures the HTTP parameters to append to the token URL. type: object noProxy: description: |- `noProxy` is a comma-separated string that can contain IPs, CIDR notation, domain names that should be excluded from proxying. IP and domain names can contain port numbers. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: string proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string scopes: description: '`scopes` defines the OAuth2 scopes used for the token request.' items: type: string type: array tlsConfig: description: |- TLS configuration to use when connecting to the OAuth2 server. It requires Prometheus >= v2.43.0. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object tokenUrl: description: '`tokenURL` configures the URL to fetch the token from.' minLength: 1 type: string required: - clientId - clientSecret - tokenUrl type: object proxyConnectHeader: additionalProperties: items: 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: array description: |- ProxyConnectHeader optionally specifies headers to send to proxies during CONNECT requests. It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: object x-kubernetes-map-type: atomic proxyFromEnvironment: description: |- Whether to use the proxy configuration defined by environment variables (HTTP_PROXY, HTTPS_PROXY, and NO_PROXY). It requires Prometheus >= v2.43.0, Alertmanager >= v0.25.0 or Thanos >= v0.32.0. type: boolean proxyUrl: description: '`proxyURL` defines the HTTP proxy server to use.' pattern: ^(http|https|socks5)://.+$ type: string queueConfig: description: QueueConfig allows tuning of the remote write queue parameters. properties: batchSendDeadline: description: BatchSendDeadline is the maximum time a sample will wait in buffer. 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 capacity: description: |- Capacity is the number of samples to buffer per shard before we start dropping them. type: integer maxBackoff: description: MaxBackoff is the maximum retry delay. 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 maxRetries: description: MaxRetries is the maximum number of times to retry a batch on recoverable errors. type: integer maxSamplesPerSend: description: MaxSamplesPerSend is the maximum number of samples per send. type: integer maxShards: description: MaxShards is the maximum number of shards, i.e. amount of concurrency. type: integer minBackoff: description: MinBackoff is the initial retry delay. Gets doubled for every retry. 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 minShards: description: MinShards is the minimum number of shards, i.e. amount of concurrency. type: integer retryOnRateLimit: description: |- Retry upon receiving a 429 status code from the remote-write storage. This is an *experimental feature*, it may change in any upcoming release in a breaking way. type: boolean sampleAgeLimit: description: |- SampleAgeLimit drops samples older than the limit. It requires Prometheus >= v2.50.0 or Thanos >= v0.32.0. 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 type: object remoteTimeout: description: Timeout for requests to the remote write endpoint. 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 roundRobinDNS: description: |- When enabled: - The remote-write mechanism will resolve the hostname via DNS. - It will randomly select one of the resolved IP addresses and connect to it. When disabled (default behavior): - The Go standard library will handle hostname resolution. - It will attempt connections to each resolved IP address sequentially. Note: The connection timeout applies to the entire resolution and connection process. If disabled, the timeout is distributed across all connection attempts. It requires Prometheus >= v3.1.0 or Thanos >= v0.38.0. type: boolean sendExemplars: description: |- Enables sending of exemplars over remote write. Note that exemplar-storage itself must be enabled using the `spec.enableFeatures` option for exemplars to be scraped in the first place. It requires Prometheus >= v2.27.0 or Thanos >= v0.24.0. type: boolean sendNativeHistograms: description: |- Enables sending of native histograms, also known as sparse histograms over remote write. It requires Prometheus >= v2.40.0 or Thanos >= v0.30.0. type: boolean sigv4: description: |- Sigv4 allows to configures AWS's Signature Verification 4 for the URL. It requires Prometheus >= v2.26.0 or Thanos >= v0.24.0. Cannot be set at the same time as `authorization`, `basicAuth`, `oauth2`, or `azureAd`. properties: accessKey: description: |- AccessKey is the AWS API key. If not specified, the environment variable `AWS_ACCESS_KEY_ID` is used. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic profile: description: Profile is the named AWS profile used to authenticate. type: string region: description: Region is the AWS region. If blank, the region from the default credentials chain used. type: string roleArn: description: RoleArn is the named AWS profile used to authenticate. type: string secretKey: description: |- SecretKey is the AWS API secret. If not specified, the environment variable `AWS_SECRET_ACCESS_KEY` is used. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object tlsConfig: description: TLS Config to use for the URL. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: |- Maximum acceptable TLS version. It requires Prometheus >= v2.41.0 or Thanos >= v0.31.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string minVersion: description: |- Minimum acceptable TLS version. It requires Prometheus >= v2.35.0 or Thanos >= v0.28.0. enum: - TLS10 - TLS11 - TLS12 - TLS13 type: string serverName: description: Used to verify the hostname for the targets. type: string type: object url: description: The URL of the endpoint to send samples to. minLength: 1 type: string writeRelabelConfigs: description: The list of remote write relabel configurations. items: description: |- RelabelConfig allows dynamic rewriting of the label set for targets, alerts, scraped samples and remote write samples. 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. `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. 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. 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. 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. It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and `DropEqual` actions. Regex capture groups are available. type: string type: object type: array required: - url type: object type: array replicas: description: Number of thanos ruler instances to deploy. format: int32 type: integer resendDelay: description: Minimum amount of time to wait before resending an alert to Alertmanager. 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 resources: description: |- Resources defines the resource requirements for single Pods. If not provided, no requests/limits will be set properties: claims: description: |- Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. properties: name: description: |- Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. type: string request: description: |- Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request. type: string required: - name type: object type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map limits: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object requests: additionalProperties: anyOf: - type: integer - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true description: |- Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object retention: default: 24h description: |- Time duration ThanosRuler shall retain data for. Default is '24h', and must match the regular expression `[0-9]+(ms|s|m|h|d|w|y)` (milliseconds seconds minutes hours days weeks years). The field has no effect when remote-write is configured since the Ruler operates in stateless mode. 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 routePrefix: description: The route prefix ThanosRuler registers HTTP handlers for. This allows thanos UI to be served on a sub-path. type: string ruleConcurrentEval: description: |- How many rules can be evaluated concurrently. It requires Thanos >= v0.37.0. format: int32 minimum: 1 type: integer ruleGracePeriod: description: |- Minimum duration between alert and restored "for" state. This is maintained only for alerts with configured "for" time greater than grace period. It requires Thanos >= v0.30.0. 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 ruleNamespaceSelector: description: |- Namespaces to be selected for Rules discovery. If unspecified, only the same namespace as the ThanosRuler object is in is used. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic ruleOutageTolerance: description: |- Max time to tolerate prometheus outage for restoring "for" state of alert. It requires Thanos >= v0.30.0. 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 ruleQueryOffset: description: |- The default rule group's query offset duration to use. It requires Thanos >= v0.38.0. 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 ruleSelector: description: |- PrometheusRule objects to be selected for rule evaluation. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic securityContext: description: |- SecurityContext holds pod-level security attributes and common container settings. This defaults to the default PodSecurityContext. properties: appArmorProfile: description: |- appArmorProfile is the AppArmor 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 loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost". type: string type: description: |- type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement. type: string required: - type type: object 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: 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---- 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 seLinuxChangePolicy: description: |- seLinuxChangePolicy defines how the container's SELinux label is applied to all volumes used by the Pod. It has no effect on nodes that do not support SELinux or to volumes does not support SELinux. Valid values are "MountOption" and "Recursive". "Recursive" means relabeling of all files on all Pod volumes by the container runtime. This may be slow for large volumes, but allows mixing privileged and unprivileged Pods sharing the same volume on the same node. "MountOption" mounts all eligible Pod volumes with `-o context` mount option. This requires all Pods that share the same volume to use the same SELinux label. It is not possible to share the same volume among privileged and unprivileged Pods. Eligible volumes are in-tree FibreChannel and iSCSI volumes, and all CSI volumes whose CSI driver announces SELinux support by setting spec.seLinuxMount: true in their CSIDriver instance. Other volumes are always re-labelled recursively. "MountOption" value is allowed only when SELinuxMount feature gate is enabled. If not specified and SELinuxMount feature gate is enabled, "MountOption" is used. If not specified and SELinuxMount feature gate is disabled, "MountOption" is used for ReadWriteOncePod volumes and "Recursive" for all other volumes. This field affects only Pods that have SELinux label set, either in PodSecurityContext or in SecurityContext of all containers. All Pods that use the same volume should use the same seLinuxChangePolicy, otherwise some pods can get stuck in ContainerCreating state. Note that this field cannot be set when spec.os.name is windows. type: string 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: 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 and fsGroup (if specified). If the SupplementalGroupsPolicy feature is enabled, the supplementalGroupsPolicy field determines whether these are in addition to or instead of any group memberships defined in the container image. If unspecified, no additional groups are added, though group memberships defined in the container image may still be used, depending on the supplementalGroupsPolicy field. Note that this field cannot be set when spec.os.name is windows. items: format: int64 type: integer type: array x-kubernetes-list-type: atomic supplementalGroupsPolicy: description: |- Defines how supplemental groups of the first container processes are calculated. Valid values are "Merge" and "Strict". If not specified, "Merge" is used. (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled and the container runtime must implement support for this feature. Note that this field cannot be set when spec.os.name is windows. type: string 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 x-kubernetes-list-type: atomic 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 serviceAccountName: description: |- ServiceAccountName is the name of the ServiceAccount to use to run the Thanos Ruler Pods. type: string serviceName: description: |- The name of the service name used by the underlying StatefulSet(s) as the governing service. If defined, the Service must be created before the ThanosRuler resource in the same namespace and it must define a selector that matches the pod labels. If empty, the operator will create and manage a headless service named `thanos-ruler-operated` for ThanosRuler resources. When deploying multiple ThanosRuler resources in the same namespace, it is recommended to specify a different value for each. See https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id for more details. minLength: 1 type: string storage: description: Storage spec to specify how storage shall be used. properties: disableMountSubPath: description: 'Deprecated: subPath usage will be removed in a future release.' type: boolean emptyDir: description: |- EmptyDirVolumeSource to be used by the StatefulSet. If specified, it takes precedence over `ephemeral` and `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: 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: |- EphemeralVolumeSource to be used by the StatefulSet. This is a beta field in k8s 1.21 and GA in 1.15. For lower versions, starting with k8s 1.19, it requires enabling the GenericEphemeralVolume feature gate. More info: https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volumes 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). 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. This field is read-only and no changes will be made by Kubernetes to the PVC after it has been created. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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/volume-attributes-classes/ (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). 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 volumeClaimTemplate: description: |- Defines the PVC spec to be used by the Prometheus StatefulSets. The easiest way to use a volume that cannot be automatically provisioned is to use a label selector alongside manually created PersistentVolumes. 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: 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. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/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: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/ type: string type: object spec: description: |- 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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/volume-attributes-classes/ (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). 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: 'Deprecated: this field is never set.' 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 x-kubernetes-list-type: atomic allocatedResourceStatuses: additionalProperties: description: |- When a controller receives persistentvolume claim update with ClaimResourceStatus for a resource that it does not recognizes, then it should ignore that update and let other controllers handle it. type: string description: "allocatedResourceStatuses stores status of resource being resized for the given PVC.\nKey names follow standard Kubernetes label syntax. Valid values are either:\n\t* Un-prefixed keys:\n\t\t- storage - the capacity of the volume.\n\t* Custom resources must use implementation-defined prefixed names such as \"example.com/my-custom-resource\"\nApart from above values - keys that are unprefixed or have kubernetes.io prefix are considered\nreserved and hence may not be used.\n\nClaimResourceStatus can be in any of following states:\n\t- ControllerResizeInProgress:\n\t\tState set when resize controller starts resizing the volume in control-plane.\n\t- ControllerResizeFailed:\n\t\tState set when resize has failed in resize controller with a terminal error.\n\t- NodeResizePending:\n\t\tState set when resize controller has finished resizing the volume but further resizing of\n\t\tvolume is needed on the node.\n\t- NodeResizeInProgress:\n\t\tState set when kubelet starts resizing the volume.\n\t- NodeResizeFailed:\n\t\tState set when resizing has failed in kubelet with a terminal error. Transient errors don't set\n\t\tNodeResizeFailed.\nFor example: if expanding a PVC for more capacity - this field can be one of the following states:\n\t- pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeInProgress\"\n - pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeFailed\"\n - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizePending\"\n - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeInProgress\"\n - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeFailed\"\nWhen this field is not set, it means that no resize operation is in progress for the given PVC.\n\nA controller that receives PVC update with previously unknown resourceName or ClaimResourceStatus\nshould ignore the update for the purpose it was designed. For example - a controller that\nonly is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid\nresources associated with PVC.\n\nThis is an alpha field and requires enabling RecoverVolumeExpansionFailure feature." type: object x-kubernetes-map-type: granular 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 tracks the resources allocated to a PVC including its capacity.\nKey names follow standard Kubernetes label syntax. Valid values are either:\n\t* Un-prefixed keys:\n\t\t- storage - the capacity of the volume.\n\t* Custom resources must use implementation-defined prefixed names such as \"example.com/my-custom-resource\"\nApart from above values - keys that are unprefixed or have kubernetes.io prefix are considered\nreserved and hence may not be used.\n\nCapacity reported here may be larger than the actual capacity when a volume expansion operation\nis requested.\nFor storage quota, the larger value from allocatedResources and PVC.spec.resources is used.\nIf allocatedResources is not set, PVC.spec.resources alone is used for quota calculation.\nIf a volume expansion capacity request is lowered, allocatedResources is only\nlowered if there are no expansion operations in progress and if the actual volume capacity\nis equal or lower than the requested capacity.\n\nA controller that receives PVC update with previously unknown resourceName\nshould ignore the update for the purpose it was designed. For example - a controller that\nonly is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid\nresources associated with PVC.\n\nThis 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 'Resizing'. items: description: PersistentVolumeClaimCondition contains 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 "Resizing" that means the underlying persistent volume is being resized. type: string status: description: |- Status is the status of the condition. Can be True, False, Unknown. More info: https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/persistent-volume-claim-v1/#:~:text=state%20of%20pvc-,conditions.status,-(string)%2C%20required type: string type: description: |- Type is the type of the condition. More info: https://kubernetes.io/docs/reference/kubernetes-api/config-and-storage-resources/persistent-volume-claim-v1/#:~:text=set%20to%20%27ResizeStarted%27.-,PersistentVolumeClaimCondition,-contains%20details%20about type: string required: - status - type type: object type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map currentVolumeAttributesClassName: description: |- currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using. When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim This is a beta field and requires enabling VolumeAttributesClass feature (off by default). type: string modifyVolumeStatus: description: |- ModifyVolumeStatus represents the status object of ControllerModifyVolume operation. When this is unset, there is no ModifyVolume operation being attempted. This is a beta field and requires enabling VolumeAttributesClass feature (off by default). properties: status: description: "status is the status of the ControllerModifyVolume operation. It can be in any of following states:\n - Pending\n Pending indicates that the PersistentVolumeClaim cannot be modified due to unmet requirements, such as\n the specified VolumeAttributesClass not existing.\n - InProgress\n InProgress indicates that the volume is being modified.\n - Infeasible\n Infeasible indicates that the request has been rejected as invalid by the CSI driver. To\n\t resolve the error, a valid VolumeAttributesClass needs to be specified.\nNote: New statuses can be added in the future. Consumers should check for unknown statuses and fail appropriately." type: string targetVolumeAttributesClassName: description: targetVolumeAttributesClassName is the name of the VolumeAttributesClass the PVC currently being reconciled type: string required: - status type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string type: object type: object type: object terminationGracePeriodSeconds: description: |- Optional duration in seconds the pod needs to terminate gracefully. Value must be non-negative integer. The value zero indicates stop immediately via the kill signal (no opportunity to shut down) which may lead to data corruption. Defaults to 120 seconds. format: int64 minimum: 0 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: If specified, the pod's 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic matchLabelKeys: description: |- MatchLabelKeys is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. MatchLabelKeys cannot be set when LabelSelector isn't set. Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. 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. 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. format: int32 type: integer nodeAffinityPolicy: description: |- NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. type: string nodeTaintsPolicy: description: |- NodeTaintsPolicy indicates how we will treat node taints when calculating pod topology spread skew. Options are: - Honor: nodes without taints, along with tainted nodes for which the incoming pod has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. 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 tracingConfig: description: |- Configures tracing. The configuration format is defined at https://thanos.io/tip/thanos/tracing.md/#configuration This is an *experimental feature*, it may change in any upcoming release in a breaking way. The operator performs no validation of the configuration. `tracingConfigFile` takes precedence over this field. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic tracingConfigFile: description: |- Configures the path of the tracing configuration file. The configuration format is defined at https://thanos.io/tip/thanos/tracing.md/#configuration This is an *experimental feature*, it may change in any upcoming release in a breaking way. The operator performs no validation of the configuration file. This field takes precedence over `tracingConfig`. type: string version: description: Version of Thanos to be deployed. type: string volumeMounts: description: |- VolumeMounts allows configuration of additional VolumeMounts on the output StatefulSet definition. VolumeMounts specified will be appended to other VolumeMounts in the ruler 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. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None). 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 recursiveReadOnly: description: |- RecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled. type: string 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. properties: awsElasticBlockStore: description: |- awsElasticBlockStore represents an AWS Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Deprecated: AWSElasticBlockStore is deprecated. All operations for the in-tree awsElasticBlockStore type are redirected to the ebs.csi.aws.com CSI driver. 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 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. Deprecated: AzureDisk is deprecated. All operations for the in-tree azureDisk type are redirected to the disk.csi.azure.com CSI driver. 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: default: ext4 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: default: false 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. Deprecated: AzureFile is deprecated. All operations for the in-tree azureFile type are redirected to the file.csi.azure.com CSI driver. 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. Deprecated: CephFS is deprecated and the in-tree cephfs type is no longer supported. 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: Cinder is deprecated. All operations for the in-tree cinder type are redirected to the cinder.csi.openstack.org CSI driver. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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 x-kubernetes-list-type: atomic name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: 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. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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, namespace and uid 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 x-kubernetes-list-type: atomic 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. 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). Use PersistentVolumeClaim or one of the vendor-specific APIs for volumes that persist for longer than the lifecycle of an individual pod. 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. 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). 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. This field is read-only and no changes will be made by Kubernetes to the PVC after it has been created. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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/volume-attributes-classes/ (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). 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. 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic type: object flexVolume: description: |- flexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. Deprecated: FlexVolume is deprecated. Consider using a CSIDriver instead. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: Flocker is deprecated and the in-tree flocker type is no longer supported. 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. Deprecated: GCEPersistentDisk is deprecated. All operations for the in-tree gcePersistentDisk type are redirected to the pd.csi.storage.gke.io CSI driver. 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 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. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported. 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 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 image: description: |- image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided: - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. The volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro) and non-executable files (noexec). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: pullPolicy: description: |- Policy for pulling OCI objects. Possible values are: Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. type: string reference: description: |- Required: Image or artifact reference to be used. Behaves in the same way as pod.spec.containers[*].image. Pull secrets will be assembled in the same way as for the container image by looking up node credentials, SA image pull secrets, and pod spec image pull secrets. 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 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 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: default: default 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 x-kubernetes-list-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: PhotonPersistentDisk is deprecated and the in-tree photonPersistentDisk type is no longer supported. 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. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on. 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. Each entry in this list handles one source. items: description: |- Projection that may be projected along with other supported volume types. Exactly one of these fields must be set. properties: clusterTrustBundle: description: |- ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. Alpha, gated by the ClusterTrustBundleProjection feature gate. ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. 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 x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic 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 x-kubernetes-list-type: atomic name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: 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, namespace and uid 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 x-kubernetes-list-type: atomic 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 x-kubernetes-list-type: atomic name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: 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 x-kubernetes-list-type: atomic type: object quobyte: description: |- quobyte represents a Quobyte mount on the host that shares a pod's lifetime. Deprecated: Quobyte is deprecated and the in-tree quobyte type is no longer supported. 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. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. 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 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: default: /etc/ceph/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 x-kubernetes-list-type: atomic pool: default: rbd 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string type: object x-kubernetes-map-type: atomic user: default: admin 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. Deprecated: ScaleIO is deprecated and the in-tree scaleIO type is no longer supported. properties: fsType: default: xfs 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string type: object x-kubernetes-map-type: atomic sslEnabled: description: sslEnabled Flag enable/disable SSL communication with Gateway, default false type: boolean storageMode: default: ThinProvisioned 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 x-kubernetes-list-type: atomic 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. Deprecated: StorageOS is deprecated and the in-tree storageos type is no longer supported. 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string 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. Deprecated: VsphereVolume is deprecated. All operations for the in-tree vsphereVolume type are redirected to the csi.vsphere.vmware.com CSI driver. 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 web: description: Defines the configuration of the ThanosRuler web server. properties: httpConfig: description: Defines HTTP parameters for web server. properties: headers: description: List of headers that can be added to HTTP responses. properties: contentSecurityPolicy: description: |- Set the Content-Security-Policy header to HTTP responses. Unset if blank. type: string strictTransportSecurity: description: |- Set the Strict-Transport-Security header to HTTP responses. Unset if blank. Please make sure that you use this with care as this header might force browsers to load Prometheus and the other applications hosted on the same domain and subdomains over HTTPS. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security type: string xContentTypeOptions: description: |- Set the X-Content-Type-Options header to HTTP responses. Unset if blank. Accepted value is nosniff. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options enum: - "" - NoSniff type: string xFrameOptions: description: |- Set the X-Frame-Options header to HTTP responses. Unset if blank. Accepted values are deny and sameorigin. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options enum: - "" - Deny - SameOrigin type: string xXSSProtection: description: |- Set the X-XSS-Protection header to all responses. Unset if blank. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection type: string type: object http2: description: |- Enable HTTP/2 support. Note that HTTP/2 is only supported with TLS. When TLSConfig is not configured, HTTP/2 will be disabled. Whenever the value of the field changes, a rolling update will be triggered. type: boolean type: object tlsConfig: description: Defines the TLS parameters for HTTPS. properties: cert: description: |- Secret or ConfigMap containing the TLS certificate for the web server. Either `keySecret` or `keyFile` must be defined. It is mutually exclusive with `certFile`. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object certFile: description: |- Path to the TLS certificate file in the container for the web server. Either `keySecret` or `keyFile` must be defined. It is mutually exclusive with `cert`. type: string cipherSuites: description: |- List of supported cipher suites for TLS versions up to TLS 1.2. If not defined, the Go default cipher suites are used. Available cipher suites are documented in the Go documentation: https://golang.org/pkg/crypto/tls/#pkg-constants items: type: string type: array client_ca: description: |- Secret or ConfigMap containing the CA certificate for client certificate authentication to the server. It is mutually exclusive with `clientCAFile`. properties: configMap: description: ConfigMap containing data to use for the targets. properties: key: description: The key to select. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the ConfigMap or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic 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: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic type: object clientAuthType: description: |- The server policy for client TLS authentication. For more detail on clientAuth options: https://golang.org/pkg/crypto/tls/#ClientAuthType type: string clientCAFile: description: |- Path to the CA certificate file for client certificate authentication to the server. It is mutually exclusive with `client_ca`. type: string curvePreferences: description: |- Elliptic curves that will be used in an ECDHE handshake, in preference order. Available curves are documented in the Go documentation: https://golang.org/pkg/crypto/tls/#CurveID items: type: string type: array keyFile: description: |- Path to the TLS private key file in the container for the web server. If defined, either `cert` or `certFile` must be defined. It is mutually exclusive with `keySecret`. type: string keySecret: description: |- Secret containing the TLS private key for the web server. Either `cert` or `certFile` must be defined. It is mutually exclusive with `keyFile`. properties: key: description: The key of the secret to select from. Must be a valid secret key. type: string name: default: "" description: |- Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: description: Specify whether the Secret or its key must be defined type: boolean required: - key type: object x-kubernetes-map-type: atomic maxVersion: description: Maximum TLS version that is acceptable. type: string minVersion: description: Minimum TLS version that is acceptable. type: string preferServerCipherSuites: description: |- Controls whether the server selects the client's most preferred cipher suite, or the server's most preferred cipher suite. If true then the server's preference, as expressed in the order of elements in cipherSuites, is used. type: boolean type: object type: object type: object status: description: |- Most recent observed status of the ThanosRuler cluster. Read-only. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status properties: availableReplicas: description: |- Total number of available pods (ready for at least minReadySeconds) targeted by this ThanosRuler deployment. format: int32 type: integer conditions: description: The current state of the ThanosRuler object. items: description: |- Condition represents the state of the resources associated with the Prometheus, Alertmanager or ThanosRuler resource. properties: lastTransitionTime: description: lastTransitionTime is the time of the last update to the current status property. format: date-time type: string message: description: Human-readable message indicating details for the condition's last transition. 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[].observedGeneration` is 9, the condition is out of date with respect to the current state of the instance. format: int64 type: integer reason: description: Reason for the condition's last transition. type: string status: description: Status of the condition. minLength: 1 type: string type: description: Type of the condition being reported. minLength: 1 type: string required: - lastTransitionTime - status - type type: object type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map paused: description: |- Represents whether any actions on the underlying managed objects are being performed. Only delete actions will be performed. type: boolean replicas: description: |- Total number of non-terminated pods targeted by this ThanosRuler deployment (their labels match the selector). format: int32 type: integer unavailableReplicas: description: Total number of unavailable pods targeted by this ThanosRuler deployment. format: int32 type: integer updatedReplicas: description: |- Total number of non-terminated pods targeted by this ThanosRuler deployment 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: status: {} ================================================ FILE: hack/config/monitoring/crds/README.md ================================================ The CRDs in this directory were downloaded from https://github.com/prometheus-operator/kube-prometheus/tree/v0.16.0/manifests/setup. Bump the version in [`update.sh`](../update.sh) and run the script to update the CRDs. ================================================ FILE: hack/config/monitoring/crds/kustomization.yaml ================================================ # Code generated by update.sh, DO NOT EDIT. apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization labels: - includeSelectors: true pairs: app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.85.0 resources: - 0alertmanagerConfigCustomResourceDefinition.yaml - 0alertmanagerCustomResourceDefinition.yaml - 0podmonitorCustomResourceDefinition.yaml - 0probeCustomResourceDefinition.yaml - 0prometheusagentCustomResourceDefinition.yaml - 0prometheusCustomResourceDefinition.yaml - 0prometheusruleCustomResourceDefinition.yaml - 0scrapeconfigCustomResourceDefinition.yaml - 0servicemonitorCustomResourceDefinition.yaml - 0thanosrulerCustomResourceDefinition.yaml ================================================ FILE: hack/config/monitoring/default/dashboards/client-go.json ================================================ { "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": 0, "links": [], "liveNow": false, "panels": [ { "collapsed": false, "datasource": { "type": "datasource", "uid": "grafana" }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 9, "panels": [], "title": "Request Rate", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic", "seriesBy": "min" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "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 } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 1 }, "id": 7, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(rest_client_requests_total{job=\"$job\",pod=~\"$pod\",method=~\"$verb\",code=~\"$code\"}[$__rate_interval])) by (pod)", "interval": "", "legendFormat": "{{pod}}", "range": true, "refId": "A" } ], "title": "Request Rate by pod", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byName", "options": "error" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "success" }, "properties": [ { "id": "color", "value": { "fixedColor": "green", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "requeue" }, "properties": [ { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "requeue_after" }, "properties": [ { "id": "color", "value": { "fixedColor": "blue", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 1 }, "id": 21, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(rest_client_requests_total{job=\"$job\",pod=~\"$pod\",method=~\"$verb\",code=~\"$code\"}[$__rate_interval])) by (code)", "interval": "", "legendFormat": "{{result}}", "range": true, "refId": "A" } ], "title": "Request Rate by code", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byName", "options": "error" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "success" }, "properties": [ { "id": "color", "value": { "fixedColor": "green", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "requeue" }, "properties": [ { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "requeue_after" }, "properties": [ { "id": "color", "value": { "fixedColor": "blue", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 10 }, "id": 36, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(rest_client_requests_total{job=\"$job\",pod=~\"$pod\",method=~\"$verb\",code=~\"$code\"}[$__rate_interval])) by (method)", "interval": "", "legendFormat": "{{result}}", "range": true, "refId": "A" } ], "title": "Request Rate by verb", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 19 }, "id": 32, "panels": [], "title": "Request / Response Sizes", "type": "row" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "decbytes" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 20 }, "id": 23, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile($percentile/100, sum(rate(rest_client_request_size_bytes_bucket{job=\"$job\",pod=~\"$pod\"}[$__rate_interval])) by (pod,le))", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{pod}}", "range": true, "refId": "A" } ], "title": "Request Size by pod (P$percentile)", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "decbytes" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 20 }, "id": 37, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile($percentile/100, sum(rate(rest_client_request_size_bytes_bucket{job=\"$job\",pod=~\"$pod\",verb=~\"$verb\"}[$__rate_interval])) by (verb,le))", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{verb}}", "range": true, "refId": "A" } ], "title": "Request Size by verb (P$percentile)", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "decbytes" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 29 }, "id": 38, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile($percentile/100, sum(rate(rest_client_response_size_bytes_bucket{job=\"$job\",pod=~\"$pod\"}[$__rate_interval])) by (pod,le))", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{pod}}", "range": true, "refId": "A" } ], "title": "Response Size by pod (P$percentile)", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "decbytes" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 29 }, "id": 39, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile($percentile/100, sum(rate(rest_client_response_size_bytes_bucket{job=\"$job\",pod=~\"$pod\",verb=~\"$verb\"}[$__rate_interval])) by (verb,le))", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{verb}}", "range": true, "refId": "A" } ], "title": "Response Size by verb (P$percentile)", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 38 }, "id": 41, "panels": [], "title": "Rate Limiter", "type": "row" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 39 }, "id": 42, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile($percentile/100, sum(rate(rest_client_rate_limiter_duration_seconds_bucket{job=\"$job\",pod=~\"$pod\",verb=~\"$verb\"}[$__rate_interval])) by (pod,le))", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{pod}}", "range": true, "refId": "A" } ], "title": "Rate Limiter Duration by pod (P$percentile)", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 39 }, "id": 43, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile($percentile/100, sum(rate(rest_client_rate_limiter_duration_seconds_bucket{job=\"$job\",pod=~\"$pod\",verb=~\"$verb\"}[$__rate_interval])) by (verb,le))", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{verb}}", "range": true, "refId": "A" } ], "title": "Rate Limiter Duration by verb (P$percentile)", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 38, "style": "dark", "tags": [ "controller-runtime" ], "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" }, { "allFormat": "glob", "current": { "selected": false, "text": "webhosting-operator", "value": "webhosting-operator" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(controller_runtime_reconcile_total{}, job)", "hide": 0, "includeAll": false, "multi": false, "name": "job", "options": [], "query": { "query": "label_values(controller_runtime_reconcile_total{}, job)", "refId": "StandardVariableQuery" }, "refresh": 2, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "allFormat": "glob", "allValue": ".*", "current": { "selected": true, "text": [ "All" ], "value": [ "$__all" ] }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(controller_runtime_reconcile_total{job=\"$job\"}, pod)", "hide": 0, "includeAll": true, "multi": true, "name": "pod", "options": [], "query": { "query": "label_values(controller_runtime_reconcile_total{job=\"$job\"}, pod)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "allFormat": "glob", "allValue": ".*", "current": { "selected": true, "text": [ "All" ], "value": [ "$__all" ] }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(rest_client_requests_total{job=\"$job\"}, method)", "hide": 0, "includeAll": true, "multi": true, "name": "verb", "options": [], "query": { "query": "label_values(rest_client_requests_total{job=\"$job\"}, method)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "allFormat": "glob", "allValue": ".*", "current": { "selected": true, "text": [ "All" ], "value": [ "$__all" ] }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(rest_client_requests_total{job=\"$job\"}, code)", "hide": 0, "includeAll": true, "multi": true, "name": "code", "options": [], "query": { "query": "label_values(rest_client_requests_total{job=\"$job\"}, code)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "current": { "selected": true, "text": "99", "value": "99" }, "hide": 0, "includeAll": false, "multi": false, "name": "percentile", "options": [ { "selected": false, "text": "90", "value": "90" }, { "selected": false, "text": "95", "value": "95" }, { "selected": true, "text": "99", "value": "99" } ], "query": "90,95,99", "queryValue": "", "skipUrlSync": false, "type": "custom" } ] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": {}, "timezone": "", "title": "Controller Runtime / Client-Go", "uid": "qIJCg2S4z", "version": 1, "weekStart": "" } ================================================ FILE: hack/config/monitoring/default/dashboards/controller-details.json ================================================ { "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": 0, "links": [], "liveNow": false, "panels": [ { "collapsed": false, "datasource": { "type": "datasource", "uid": "grafana" }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 9, "panels": [], "title": "Reconciliations", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic", "seriesBy": "min" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "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 } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 1 }, "id": 7, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(controller_runtime_reconcile_total{job=\"$job\",controller=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (pod)", "interval": "", "legendFormat": "{{pod}}", "range": true, "refId": "A" } ], "title": "Reconciliation Rate by pod", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byName", "options": "error" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "success" }, "properties": [ { "id": "color", "value": { "fixedColor": "green", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "requeue" }, "properties": [ { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "requeue_after" }, "properties": [ { "id": "color", "value": { "fixedColor": "blue", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 1 }, "id": 21, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(controller_runtime_reconcile_total{job=\"$job\",controller=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (result)", "interval": "", "legendFormat": "{{result}}", "range": true, "refId": "A" } ], "title": "Reconciliation Rate by result", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "continuous-GrYlRd", "seriesBy": "last" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "scheme", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "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 } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 10 }, "id": 20, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(controller_runtime_reconcile_errors_total{job=\"$job\",controller=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (pod)", "interval": "", "legendFormat": "{{pod}}", "range": true, "refId": "A" } ], "title": "Error Rate by pod", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 10 }, "id": 23, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile(0.9, sum(rate(controller_runtime_reconcile_time_seconds_bucket{job=\"$job\",controller=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (controller,le))", "format": "time_series", "instant": false, "interval": "", "legendFormat": "P90", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile(0.95, sum(rate(controller_runtime_reconcile_time_seconds_bucket{job=\"$job\",controller=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (controller,le))", "format": "time_series", "hide": false, "instant": false, "interval": "", "legendFormat": "P95", "range": true, "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile(0.99, sum(rate(controller_runtime_reconcile_time_seconds_bucket{job=\"$job\",controller=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (controller,le))", "format": "time_series", "hide": false, "instant": false, "interval": "", "legendFormat": "P99", "range": true, "refId": "C" } ], "title": "Reconciliation Time (P90, P95, P99)", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 19 }, "id": 32, "panels": [], "title": "Workers", "type": "row" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "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 } ] }, "unit": "none" }, "overrides": [ { "matcher": { "id": "byName", "options": "Max" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } }, { "id": "custom.gradientMode", "value": "none" }, { "id": "custom.fillOpacity", "value": 0 } ] } ] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 20 }, "id": 22, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(controller_runtime_active_workers{job=\"$job\",controller=~\"$controller\",pod=~\"$pod\"}) by (pod)", "interval": "", "legendFormat": "{{pod}}", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "expr": "max(controller_runtime_max_concurrent_reconciles{job=\"$job\",controller=~\"$controller\",pod=~\"$pod\"})", "hide": false, "legendFormat": "Max", "range": true, "refId": "B" } ], "title": "Active Workers by pod", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "continuous-RdYlGr" }, "custom": { "align": "auto", "cellOptions": { "type": "auto" }, "inspect": false }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "none" }, "overrides": [ { "matcher": { "id": "byName", "options": "Value" }, "properties": [ { "id": "custom.cellOptions", "value": { "mode": "gradient", "type": "color-background" } }, { "id": "custom.width", "value": 80 } ] } ] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 20 }, "id": 35, "options": { "cellHeight": "sm", "footer": { "countRows": false, "fields": "", "reducer": [ "sum" ], "show": false }, "showHeader": true, "sortBy": [] }, "pluginVersion": "9.5.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(controller_runtime_max_concurrent_reconciles{job=\"$job\",controller=~\"$controller\",pod=~\"$pod\"}) by (pod)", "format": "table", "hide": false, "instant": true, "range": false, "refId": "A" } ], "title": "Total Workers by pod", "transformations": [ { "id": "organize", "options": { "excludeByName": { "Time": true }, "indexByName": {}, "renameByName": {} } } ], "type": "table" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "Rate of unfinished work per second not observed in work duration metrics. A constant value of 1 could indicate 1 stuck worker routine.", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "area" } }, "mappings": [], "max": 2, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 1 } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 29 }, "id": 29, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(rate(workqueue_unfinished_work_seconds{job=\"$job\",name=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (pod)", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{pod}}", "range": true, "refId": "A" } ], "title": "Unfinished Work by pod", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "continuous-GrYlRd" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "scheme", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 29 }, "id": 30, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "max(workqueue_longest_running_processor_seconds{job=\"$job\",name=~\"$controller\",pod=~\"$pod\"}) by (pod)", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{name}}", "range": true, "refId": "A" } ], "title": "Longest Running Worker by pod", "type": "timeseries" }, { "collapsed": false, "datasource": { "type": "datasource", "uid": "grafana" }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 38 }, "id": 11, "panels": [], "title": "Work Queue", "type": "row" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 39 }, "id": 27, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(rate(workqueue_adds_total{job=\"$job\",name=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (pod)", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{name}}", "range": true, "refId": "A" } ], "title": "Queue Add Rate by pod", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 39 }, "id": 33, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(rate(workqueue_retries_total{job=\"$job\",name=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (pod)", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{name}}", "range": true, "refId": "A" } ], "title": "Retry Rate by pod", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 48 }, "id": 24, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile(0.9, sum(rate(workqueue_queue_duration_seconds_bucket{job=\"$job\",name=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (name,le))", "format": "time_series", "instant": false, "interval": "", "legendFormat": "P90", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile(0.95, sum(rate(workqueue_queue_duration_seconds_bucket{job=\"$job\",name=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (name,le))", "format": "time_series", "hide": false, "instant": false, "interval": "", "legendFormat": "P95", "range": true, "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile(0.99, sum(rate(workqueue_queue_duration_seconds_bucket{job=\"$job\",name=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (name,le))", "format": "time_series", "hide": false, "instant": false, "interval": "", "legendFormat": "P99", "range": true, "refId": "C" } ], "title": "Queue Duration (P90, P95, P99)", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 48 }, "id": 28, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile(0.9, sum(rate(workqueue_work_duration_seconds_bucket{job=\"$job\",name=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (name,le))", "format": "time_series", "instant": false, "interval": "", "legendFormat": "P90", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile(0.95, sum(rate(workqueue_work_duration_seconds_bucket{job=\"$job\",name=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (name,le))", "format": "time_series", "hide": false, "instant": false, "interval": "", "legendFormat": "P95", "range": true, "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile(0.99, sum(rate(workqueue_work_duration_seconds_bucket{job=\"$job\",name=~\"$controller\",pod=~\"$pod\"}[$__rate_interval])) by (name,le))", "format": "time_series", "hide": false, "instant": false, "interval": "", "legendFormat": "P99", "range": true, "refId": "C" } ], "title": "Work Duration (P90, P95, P99)", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 57 }, "id": 25, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(workqueue_depth{job=\"$job\",name=~\"$controller\",pod=~\"$pod\"}) by (pod)", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{pod}}", "range": true, "refId": "A" } ], "title": "Queue Length by pod", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 38, "style": "dark", "tags": [ "controller-runtime" ], "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" }, { "allFormat": "glob", "current": { "selected": false, "text": "webhosting-operator", "value": "webhosting-operator" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(controller_runtime_reconcile_total{}, job)", "hide": 0, "includeAll": false, "multi": false, "name": "job", "options": [], "query": { "query": "label_values(controller_runtime_reconcile_total{}, job)", "refId": "StandardVariableQuery" }, "refresh": 2, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "allFormat": "glob", "allValue": ".*", "current": { "selected": true, "text": [ "All" ], "value": [ "$__all" ] }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(controller_runtime_reconcile_total{job=\"$job\"}, pod)", "hide": 0, "includeAll": true, "multi": true, "name": "pod", "options": [], "query": { "query": "label_values(controller_runtime_reconcile_total{job=\"$job\"}, pod)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "allFormat": "glob", "current": { "selected": false, "text": "website", "value": "website" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(controller_runtime_reconcile_total{job=\"$job\"}, controller)", "hide": 0, "includeAll": false, "multi": false, "name": "controller", "options": [], "query": { "query": "label_values(controller_runtime_reconcile_total{job=\"$job\"}, controller)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": {}, "timezone": "", "title": "Controller Runtime / Controllers / Controller Details", "uid": "OjCZokmVz", "version": 1, "weekStart": "" } ================================================ FILE: hack/config/monitoring/default/dashboards/controller-runtime.json ================================================ { "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": 0, "links": [], "liveNow": false, "panels": [ { "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 35, "title": "Headlines (over time range)", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 7, "w": 9, "x": 0, "y": 1 }, "id": 39, "options": { "displayMode": "gradient", "minVizHeight": 10, "minVizWidth": 0, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true, "valueMode": "color" }, "pluginVersion": "9.5.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(rate(controller_runtime_reconcile_total{job=\"$job\",pod=~\"$pod\",controller=~\"$controller\"}[$__range])) by (controller)", "format": "time_series", "hide": false, "instant": true, "legendFormat": "__auto", "range": false, "refId": "A" } ], "title": "Reconciliation Rate", "transformations": [], "type": "bargauge" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "continuous-RdYlGr" }, "custom": { "align": "auto", "cellOptions": { "type": "auto" }, "inspect": false }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "none" }, "overrides": [ { "matcher": { "id": "byName", "options": "Value" }, "properties": [ { "id": "custom.cellOptions", "value": { "mode": "gradient", "type": "color-background" } }, { "id": "custom.width", "value": 80 } ] }, { "matcher": { "id": "byName", "options": "controller" }, "properties": [ { "id": "links", "value": [ { "title": "", "url": "/d/OjCZokmVz/controller-runtime-controllers-controller-details?var-datasource=$datasource&var-job=$job&var-controller=${__data.fields.controller}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 6, "x": 9, "y": 1 }, "id": 40, "options": { "cellHeight": "sm", "footer": { "countRows": false, "fields": "", "reducer": [ "sum" ], "show": false }, "showHeader": true, "sortBy": [ { "desc": true, "displayName": "Value" } ] }, "pluginVersion": "9.5.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(controller_runtime_max_concurrent_reconciles{job=\"$job\",pod=~\"$pod\",controller=~\"$controller\"}) by (controller)", "format": "table", "hide": false, "instant": true, "range": false, "refId": "A" } ], "title": "Total Workers by controller", "transformations": [ { "id": "organize", "options": { "excludeByName": { "Time": true }, "indexByName": {}, "renameByName": {} } } ], "type": "table" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "hideFrom": { "legend": false, "tooltip": false, "viz": false } }, "mappings": [], "unit": "s/s" }, "overrides": [] }, "gridPos": { "h": 7, "w": 9, "x": 15, "y": 1 }, "id": 38, "options": { "displayLabels": [], "legend": { "displayMode": "table", "placement": "right", "showLegend": true, "values": [ "percent" ] }, "pieType": "donut", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "tooltip": { "mode": "single", "sort": "none" } }, "pluginVersion": "8.5.5", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(rate(controller_runtime_reconcile_time_seconds_sum{job=\"$job\",pod=~\"$pod\",controller=~\"$controller\"}[$__range])) by (controller)", "format": "time_series", "hide": false, "instant": true, "legendFormat": "__auto", "range": false, "refId": "A" } ], "title": "Reconciliation Time Distribution", "transformations": [], "type": "piechart" }, { "collapsed": false, "datasource": { "type": "datasource", "uid": "grafana" }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 8 }, "id": 9, "panels": [], "title": "Reconciliations", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic", "seriesBy": "min" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "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 } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 9 }, "id": 7, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(controller_runtime_reconcile_total{job=\"$job\",pod=~\"$pod\",controller=~\"$controller\"}[$__rate_interval])) by (controller)", "interval": "", "legendFormat": "{{controller}}", "range": true, "refId": "A" } ], "title": "Reconciliation Rate by controller", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byName", "options": "error" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "success" }, "properties": [ { "id": "color", "value": { "fixedColor": "green", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "requeue" }, "properties": [ { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "requeue_after" }, "properties": [ { "id": "color", "value": { "fixedColor": "blue", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 9 }, "id": 21, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(controller_runtime_reconcile_total{job=\"$job\",pod=~\"$pod\",controller=~\"$controller\"}[$__rate_interval])) by (result)", "interval": "", "legendFormat": "{{result}}", "range": true, "refId": "A" } ], "title": "Reconciliation Rate by result", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "continuous-GrYlRd", "seriesBy": "last" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "scheme", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "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 } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 18 }, "id": 20, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(controller_runtime_reconcile_errors_total{job=\"$job\",pod=~\"$pod\",controller=~\"$controller\"}[$__rate_interval])) by (controller)", "interval": "", "legendFormat": "{{controller}}", "range": true, "refId": "A" } ], "title": "Error Rate by controller", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 18 }, "id": 23, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile($percentile/100, sum(rate(controller_runtime_reconcile_time_seconds_bucket{job=\"$job\",pod=~\"$pod\",controller=~\"$controller\"}[$__rate_interval])) by (controller,le))", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{result}}", "range": true, "refId": "A" } ], "title": "Reconciliation Time by controller (P$percentile)", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 27 }, "id": 32, "panels": [], "title": "Workers", "type": "row" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "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 } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 28 }, "id": 22, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(controller_runtime_active_workers{job=\"$job\",pod=~\"$pod\",controller=~\"$controller\"}) by (controller)", "interval": "", "legendFormat": "{{controller}}", "range": true, "refId": "A" } ], "title": "Active Workers by controller", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "continuous-RdYlGr" }, "custom": { "align": "auto", "cellOptions": { "type": "auto" }, "inspect": false }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "none" }, "overrides": [ { "matcher": { "id": "byName", "options": "Value" }, "properties": [ { "id": "custom.cellOptions", "value": { "mode": "gradient", "type": "color-background" } }, { "id": "custom.width", "value": 80 } ] }, { "matcher": { "id": "byName", "options": "controller" }, "properties": [ { "id": "links", "value": [ { "title": "", "url": "/d/OjCZokmVz/controller-runtime-controllers-controller-details?var-datasource=$datasource&var-job=$job&var-controller=${__data.fields.controller}" } ] } ] } ] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 28 }, "id": 37, "options": { "cellHeight": "sm", "footer": { "countRows": false, "fields": "", "reducer": [ "sum" ], "show": false }, "showHeader": true, "sortBy": [] }, "pluginVersion": "9.5.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(controller_runtime_max_concurrent_reconciles{job=\"$job\",pod=~\"$pod\",controller=~\"$controller\"}) by (controller)", "format": "table", "hide": false, "instant": true, "range": false, "refId": "A" } ], "title": "Total Workers by controller", "transformations": [ { "id": "organize", "options": { "excludeByName": { "Time": true }, "indexByName": {}, "renameByName": {} } } ], "type": "table" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "Rate of unfinished work per second not observed in work duration metrics. A constant value of 1 could indicate 1 stuck worker routine.", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "area" } }, "mappings": [], "max": 2, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 1 } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 37 }, "id": 29, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(rate(workqueue_unfinished_work_seconds{job=\"$job\",pod=~\"$pod\",name=~\"$controller\"}[$__rate_interval])) by (name)", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{name}}", "range": true, "refId": "A" } ], "title": "Unfinished Work by controller", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "continuous-GrYlRd" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "scheme", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 37 }, "id": 30, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "max(workqueue_longest_running_processor_seconds{job=\"$job\",pod=~\"$pod\",name=~\"$controller\"}) by (name)", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{name}}", "range": true, "refId": "A" } ], "title": "Longest Running Worker by controller", "type": "timeseries" }, { "collapsed": false, "datasource": { "type": "datasource", "uid": "grafana" }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 46 }, "id": 11, "panels": [], "title": "Work Queue", "type": "row" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 47 }, "id": 27, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(rate(workqueue_adds_total{job=\"$job\",pod=~\"$pod\",name=~\"$controller\"}[$__rate_interval])) by (name)", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{name}}", "range": true, "refId": "A" } ], "title": "Queue Add Rate by controller", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 47 }, "id": 33, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(rate(workqueue_retries_total{job=\"$job\",pod=~\"$pod\",name=~\"$controller\"}[$__rate_interval])) by (name)", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{name}}", "range": true, "refId": "A" } ], "title": "Retry Rate by controller", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 56 }, "id": 24, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile($percentile/100, sum(rate(workqueue_queue_duration_seconds_bucket{job=\"$job\",pod=~\"$pod\",name=~\"$controller\"}[$__rate_interval])) by (name,le))", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{name}}", "range": true, "refId": "A" } ], "title": "Queue Duration by controller (P$percentile)", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 56 }, "id": 28, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "histogram_quantile($percentile/100, sum(rate(workqueue_work_duration_seconds_bucket{job=\"$job\",pod=~\"$pod\",name=~\"$controller\"}[$__rate_interval])) by (name,le))", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{name}}", "range": true, "refId": "A" } ], "title": "Work Duration by controller (P$percentile)", "type": "timeseries" }, { "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": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 65 }, "id": 25, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(workqueue_depth{job=\"$job\",pod=~\"$pod\",name=~\"$controller\"}) by (name)", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{name}}", "range": true, "refId": "A" } ], "title": "Queue Length by controller", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 38, "style": "dark", "tags": [ "controller-runtime" ], "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" }, { "allFormat": "glob", "current": { "selected": false, "text": "webhosting-operator", "value": "webhosting-operator" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(controller_runtime_reconcile_total{}, job)", "hide": 0, "includeAll": false, "multi": false, "name": "job", "options": [], "query": { "query": "label_values(controller_runtime_reconcile_total{}, job)", "refId": "StandardVariableQuery" }, "refresh": 2, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "allFormat": "glob", "allValue": ".*", "current": { "selected": true, "text": [ "All" ], "value": [ "$__all" ] }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(controller_runtime_reconcile_total{job=\"$job\"}, pod)", "hide": 0, "includeAll": true, "multi": true, "name": "pod", "options": [], "query": { "query": "label_values(controller_runtime_reconcile_total{job=\"$job\"}, pod)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "allFormat": "glob", "allValue": ".*", "current": { "selected": true, "text": [ "All" ], "value": [ "$__all" ] }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(controller_runtime_reconcile_total{job=\"$job\"}, controller)", "hide": 0, "includeAll": true, "multi": true, "name": "controller", "options": [], "query": { "query": "label_values(controller_runtime_reconcile_total{job=\"$job\"}, controller)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "current": { "selected": false, "text": "99", "value": "99" }, "hide": 0, "includeAll": false, "multi": false, "name": "percentile", "options": [ { "selected": false, "text": "90", "value": "90" }, { "selected": false, "text": "95", "value": "95" }, { "selected": true, "text": "99", "value": "99" } ], "query": "90,95,99", "queryValue": "", "skipUrlSync": false, "type": "custom" } ] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": {}, "timezone": "", "title": "Controller Runtime / Controllers", "uid": "PuCBL3zVz", "version": 2, "weekStart": "" } ================================================ FILE: hack/config/monitoring/default/ensure-admin-password.sh ================================================ #!/usr/bin/env bash dir="$(dirname "$0")" file="$dir/grafana_admin_password.secret.txt" [ -f "$file" ] && exit 0 cat /dev/urandom | tr -dc "a-zA-Z0-9" | head -c 32 > "$file" ================================================ FILE: hack/config/monitoring/default/grafana_ingress.yaml ================================================ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: cert-manager.io/cluster-issuer: letsencrypt-http01 labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana name: grafana namespace: monitoring spec: rules: - host: grafana.webhosting.timebertt.dev http: paths: - backend: service: name: grafana port: name: http path: / pathType: Prefix tls: - hosts: - grafana.webhosting.timebertt.dev secretName: grafana-tls ================================================ FILE: hack/config/monitoring/default/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization components: - ../grafana-sidecar resources: - namespace.yaml - rbac-proxy_clusterrole.yaml - ../kube-prometheus - grafana_ingress.yaml generatorOptions: disableNameSuffixHash: true configMapGenerator: - files: - dashboards/client-go.json - dashboards/controller-details.json - dashboards/controller-runtime.json name: grafana-dashboards-controller namespace: monitoring options: labels: grafana_dashboard: "true" secretGenerator: - name: grafana-admin namespace: monitoring literals: - username=admin files: - password=grafana_admin_password.secret.txt patches: - path: patch_grafana_admin.yaml - path: patch_prometheus.yaml - path: patch_grafana_networkpolicy.yaml target: group: networking.k8s.io version: v1 kind: NetworkPolicy name: grafana namespace: monitoring - path: patch_kubelet_metrics.yaml target: group: monitoring.coreos.com version: v1 kind: ServiceMonitor name: kubelet namespace: monitoring - path: patch_kubestatemetrics.yaml target: group: apps version: v1 kind: Deployment name: kube-state-metrics namespace: monitoring - path: patch_kubestatemetrics_servicemonitor.yaml target: group: monitoring.coreos.com version: v1 kind: ServiceMonitor name: kube-state-metrics namespace: monitoring ================================================ FILE: hack/config/monitoring/default/namespace.yaml ================================================ apiVersion: v1 kind: Namespace metadata: name: monitoring ================================================ FILE: hack/config/monitoring/default/patch_grafana_admin.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: grafana namespace: monitoring spec: template: spec: containers: - name: grafana env: - name: GF_SECURITY_ADMIN_PASSWORD valueFrom: secretKeyRef: name: grafana-admin key: password - name: GF_AUTH_ANONYMOUS_ENABLED value: "true" - name: GF_AUTH_ANONYMOUS_ORG_ROLE value: "Viewer" - name: GF_USERS_VIEWERS_CAN_EDIT value: "false" - name: GF_ALERTING_ENABLED value: "false" - name: GF_UNIFIED_ALERTING_ENABLED value: "false" - name: GF_USERS_DEFAULT_THEME value: "light" ================================================ FILE: hack/config/monitoring/default/patch_grafana_networkpolicy.yaml ================================================ - op: add path: /spec/ingress/- value: from: - podSelector: matchLabels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/component: controller namespaceSelector: matchLabels: app.kubernetes.io/name: ingress-nginx ports: - port: 3000 protocol: TCP ================================================ FILE: hack/config/monitoring/default/patch_kubelet_metrics.yaml ================================================ # drop storage operation duration metrics (high cardinality) - op: add path: /spec/endpoints/0/metricRelabelings/- value: sourceLabels: [__name__] regex: storage_operation_duration_seconds_.+ action: drop # drop runtime operation duration metrics (high cardinality) - op: add path: /spec/endpoints/0/metricRelabelings/- value: sourceLabels: [__name__] regex: kubelet_runtime_operations_duration_seconds_.+ action: drop # drop metrics for project namespaces - op: add path: /spec/endpoints/0/metricRelabelings/- value: sourceLabels: [namespace] regex: project-.+ action: drop # drop cadvisor metrics for project namespaces - op: add path: /spec/endpoints/1/metricRelabelings/- value: sourceLabels: [namespace] regex: project-.+ action: drop # increase cadvisor scrape interval - op: replace path: /spec/endpoints/1/interval value: 10s ================================================ FILE: hack/config/monitoring/default/patch_kubestatemetrics.yaml ================================================ # drop kube-state-metrics metrics for project namespaces - op: add path: /spec/template/spec/containers/0/args/- value: --namespaces=cert-manager,default,experiment,external-dns,ingress-nginx,kube-node-lease,kube-public,kube-system,kyverno,monitoring,parca,sharding-system,webhosting-system # label.prometheus.io/run_id is injected by experiment into observed pods (sharder and webhosting-operator). # Add the run_id label to kube_pod_labels. This allows joining cadvisor metrics with kube_pod_labels for selecting # metrics by experiment run ID. - op: add path: /spec/template/spec/containers/0/args/- value: # this flag doesn't support wildcard patterns --metric-labels-allowlist=pods=[label.prometheus.io/run_id] ================================================ FILE: hack/config/monitoring/default/patch_kubestatemetrics_servicemonitor.yaml ================================================ # label map for label.prometheus.io/* labels - op: add path: /spec/endpoints/0/metricRelabelings/- value: action: labelmap regex: "label_label_prometheus_io_(.*)" replacement: "${1}" - op: add path: /spec/endpoints/0/metricRelabelings/- value: action: labeldrop regex: "label_label_prometheus_io_(.*)" ================================================ FILE: hack/config/monitoring/default/patch_prometheus.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: name: k8s namespace: monitoring spec: replicas: 1 # don't need HA for our purposes evaluationInterval: 15s alerting: null resources: requests: cpu: 3000m memory: 12Gi limits: cpu: 4000m # replaying WAL takes some CPU memory: 12Gi ================================================ FILE: hack/config/monitoring/default/rbac-proxy_clusterrole.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: rbac-proxy rules: - apiGroups: - authentication.k8s.io resources: - tokenreviews verbs: - create - apiGroups: - authorization.k8s.io resources: - subjectaccessreviews verbs: - create ================================================ FILE: hack/config/monitoring/grafana-sidecar/dashboards-sidecar.yaml ================================================ apiVersion: 1 providers: - folder: Default folderUid: "" name: "1" options: path: /grafana-dashboard-definitions-sidecar/0 orgId: 1 type: file ================================================ FILE: hack/config/monitoring/grafana-sidecar/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component generatorOptions: disableNameSuffixHash: true configMapGenerator: - name: grafana-dashboards namespace: monitoring behavior: merge files: - dashboards-sidecar.yaml patches: - path: patch_grafana_sidecar.yaml resources: - sidecar_clusterrole.yaml - sidecar_clusterrolebinding.yaml ================================================ FILE: hack/config/monitoring/grafana-sidecar/patch_grafana_sidecar.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: grafana namespace: monitoring spec: template: spec: automountServiceAccountToken: true containers: - name: grafana-sc-dashboard image: quay.io/kiwigrid/k8s-sidecar:1.30.11 imagePullPolicy: IfNotPresent env: - name: METHOD value: WATCH - name: LABEL value: grafana_dashboard - name: FOLDER value: /grafana-dashboard-definitions-sidecar/0 - name: RESOURCE value: configmap volumeMounts: - name: sc-dashboard-volume mountPath: /grafana-dashboard-definitions-sidecar/0 - name: grafana volumeMounts: - name: sc-dashboard-volume mountPath: /grafana-dashboard-definitions-sidecar/0 volumes: - name: sc-dashboard-volume emptyDir: {} ================================================ FILE: hack/config/monitoring/grafana-sidecar/sidecar_clusterrole.yaml ================================================ kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: labels: app.kubernetes.io/name: grafana name: grafana-sidecar rules: - apiGroups: - "" resources: - configmaps verbs: - get - list - watch ================================================ FILE: hack/config/monitoring/grafana-sidecar/sidecar_clusterrolebinding.yaml ================================================ kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: labels: app.kubernetes.io/name: grafana name: grafana-sidecar roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: grafana-sidecar subjects: - kind: ServiceAccount name: grafana namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/README.md ================================================ The manifests in this directory were downloaded from https://github.com/prometheus-operator/kube-prometheus/tree/v0.16.0/manifests. Bump the version in [`update.sh`](../update.sh) and run the script to update the CRDs. ================================================ FILE: hack/config/monitoring/kube-prometheus/blackboxExporter-clusterRole.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.27.0 name: blackbox-exporter rules: - apiGroups: - authentication.k8s.io resources: - tokenreviews verbs: - create - apiGroups: - authorization.k8s.io resources: - subjectaccessreviews verbs: - create ================================================ FILE: hack/config/monitoring/kube-prometheus/blackboxExporter-clusterRoleBinding.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.27.0 name: blackbox-exporter roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: blackbox-exporter subjects: - kind: ServiceAccount name: blackbox-exporter namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/blackboxExporter-configuration.yaml ================================================ apiVersion: v1 data: config.yml: |- "modules": "http_2xx": "http": "preferred_ip_protocol": "ip4" "prober": "http" "http_post_2xx": "http": "method": "POST" "preferred_ip_protocol": "ip4" "prober": "http" "irc_banner": "prober": "tcp" "tcp": "preferred_ip_protocol": "ip4" "query_response": - "send": "NICK prober" - "send": "USER prober prober prober :prober" - "expect": "PING :([^ ]+)" "send": "PONG ${1}" - "expect": "^:[^ ]+ 001" "pop3s_banner": "prober": "tcp" "tcp": "preferred_ip_protocol": "ip4" "query_response": - "expect": "^+OK" "tls": true "tls_config": "insecure_skip_verify": false "ssh_banner": "prober": "tcp" "tcp": "preferred_ip_protocol": "ip4" "query_response": - "expect": "^SSH-2.0-" "tcp_connect": "prober": "tcp" "tcp": "preferred_ip_protocol": "ip4" kind: ConfigMap metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.27.0 name: blackbox-exporter-configuration namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/blackboxExporter-deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.27.0 name: blackbox-exporter namespace: monitoring spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus template: metadata: annotations: kubectl.kubernetes.io/default-container: blackbox-exporter labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.27.0 spec: automountServiceAccountToken: true containers: - args: - --config.file=/etc/blackbox_exporter/config.yml - --web.listen-address=:19115 image: quay.io/prometheus/blackbox-exporter:v0.27.0 name: blackbox-exporter ports: - containerPort: 19115 name: http resources: limits: cpu: 20m memory: 40Mi requests: cpu: 10m memory: 20Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65534 runAsNonRoot: true runAsUser: 65534 volumeMounts: - mountPath: /etc/blackbox_exporter/ name: config readOnly: true - args: - --webhook-url=http://localhost:19115/-/reload - --volume-dir=/etc/blackbox_exporter/ image: ghcr.io/jimmidyson/configmap-reload:v0.15.0 name: module-configmap-reloader resources: limits: cpu: 20m memory: 40Mi requests: cpu: 10m memory: 20Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65534 runAsNonRoot: true runAsUser: 65534 terminationMessagePath: /dev/termination-log terminationMessagePolicy: FallbackToLogsOnError volumeMounts: - mountPath: /etc/blackbox_exporter/ name: config readOnly: true - args: - --secure-listen-address=:9115 - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 - --upstream=http://127.0.0.1:19115/ image: quay.io/brancz/kube-rbac-proxy:v0.19.1 name: kube-rbac-proxy ports: - containerPort: 9115 name: https resources: limits: cpu: 20m memory: 40Mi requests: cpu: 10m memory: 20Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65532 runAsNonRoot: true runAsUser: 65532 seccompProfile: type: RuntimeDefault nodeSelector: kubernetes.io/os: linux serviceAccountName: blackbox-exporter volumes: - configMap: name: blackbox-exporter-configuration name: config ================================================ FILE: hack/config/monitoring/kube-prometheus/blackboxExporter-networkPolicy.yaml ================================================ apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.27.0 name: blackbox-exporter namespace: monitoring spec: egress: - {} ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: prometheus ports: - port: 9115 protocol: TCP - port: 19115 protocol: TCP podSelector: matchLabels: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus policyTypes: - Egress - Ingress ================================================ FILE: hack/config/monitoring/kube-prometheus/blackboxExporter-service.yaml ================================================ apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.27.0 name: blackbox-exporter namespace: monitoring spec: ports: - name: https port: 9115 targetPort: https - name: probe port: 19115 targetPort: http selector: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus ================================================ FILE: hack/config/monitoring/kube-prometheus/blackboxExporter-serviceAccount.yaml ================================================ apiVersion: v1 automountServiceAccountToken: false kind: ServiceAccount metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.27.0 name: blackbox-exporter namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/blackboxExporter-serviceMonitor.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.27.0 name: blackbox-exporter namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 30s path: /metrics port: https scheme: https tlsConfig: insecureSkipVerify: true selector: matchLabels: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus ================================================ FILE: hack/config/monitoring/kube-prometheus/grafana-config.yaml ================================================ apiVersion: v1 kind: Secret metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-config namespace: monitoring stringData: grafana.ini: | [date_formats] default_timezone = UTC type: Opaque ================================================ FILE: hack/config/monitoring/kube-prometheus/grafana-dashboardDatasources.yaml ================================================ apiVersion: v1 kind: Secret metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-datasources namespace: monitoring stringData: datasources.yaml: |- { "apiVersion": 1, "datasources": [ { "access": "proxy", "editable": false, "name": "prometheus", "orgId": 1, "type": "prometheus", "url": "http://prometheus-k8s.monitoring.svc:9090", "version": 1 } ] } type: Opaque ================================================ FILE: hack/config/monitoring/kube-prometheus/grafana-dashboardDefinitions.yaml ================================================ apiVersion: v1 items: - apiVersion: v1 data: alertmanager-overview.json: |- { "graphTooltip": 1, "panels": [ { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 1, "panels": [ ], "title": "Alerts", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "description": "current set of alerts stored in the Alertmanager", "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "none" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 1 }, "id": 2, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum(alertmanager_alerts{namespace=~\"$namespace\",service=~\"$service\"}) by (namespace,service,instance)", "intervalFactor": 2, "legendFormat": "{{instance}}" } ], "title": "Alerts", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "description": "rate of successful and invalid alerts received by the Alertmanager", "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 1 }, "id": 3, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum(rate(alertmanager_alerts_received_total{namespace=~\"$namespace\",service=~\"$service\"}[$__rate_interval])) by (namespace,service,instance)", "intervalFactor": 2, "legendFormat": "{{instance}} Received" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum(rate(alertmanager_alerts_invalid_total{namespace=~\"$namespace\",service=~\"$service\"}[$__rate_interval])) by (namespace,service,instance)", "intervalFactor": 2, "legendFormat": "{{instance}} Invalid" } ], "title": "Alerts receive rate", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 8 }, "id": 4, "panels": [ ], "title": "Notifications", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "description": "rate of successful and invalid notifications sent by the Alertmanager", "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 9 }, "id": 5, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "repeat": "integration", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum(rate(alertmanager_notifications_total{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (integration,namespace,service,instance)", "intervalFactor": 2, "legendFormat": "{{instance}} Total" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum(rate(alertmanager_notifications_failed_total{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (integration,namespace,service,instance)", "intervalFactor": 2, "legendFormat": "{{instance}} Failed" } ], "title": "$integration: Notifications Send Rate", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "description": "latency of notifications sent by the Alertmanager", "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "s" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 9 }, "id": 6, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "repeat": "integration", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "histogram_quantile(0.99,\n sum(rate(alertmanager_notification_latency_seconds_bucket{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (le,namespace,service,instance)\n)\n", "intervalFactor": 2, "legendFormat": "{{instance}} 99th Percentile" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "histogram_quantile(0.50,\n sum(rate(alertmanager_notification_latency_seconds_bucket{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (le,namespace,service,instance)\n)\n", "intervalFactor": 2, "legendFormat": "{{instance}} Median" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum(rate(alertmanager_notification_latency_seconds_sum{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (namespace,service,instance)\n/\nsum(rate(alertmanager_notification_latency_seconds_count{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (namespace,service,instance)\n", "intervalFactor": 2, "legendFormat": "{{instance}} Average" } ], "title": "$integration: Notification Duration", "type": "timeseries" } ], "schemaVersion": 39, "tags": [ "alertmanager-mixin" ], "templating": { "list": [ { "current": { "selected": false, "text": "Prometheus", "value": "Prometheus" }, "hide": 0, "label": "Data Source", "name": "datasource", "query": "prometheus", "type": "datasource" }, { "current": { "selected": false, "text": "", "value": "" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "includeAll": false, "label": "namespace", "name": "namespace", "query": "label_values(alertmanager_alerts, namespace)", "refresh": 2, "sort": 1, "type": "query" }, { "current": { "selected": false, "text": "", "value": "" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "includeAll": false, "label": "service", "name": "service", "query": "label_values(alertmanager_alerts, service)", "refresh": 2, "sort": 1, "type": "query" }, { "current": { "selected": false, "text": "$__all", "value": "$__all" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 2, "includeAll": true, "name": "integration", "query": "label_values(alertmanager_notifications_total{integration=~\".*\"}, integration)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": { "refresh_intervals": [ "30s" ] }, "timezone": "utc", "title": "Alertmanager / Overview", "uid": "alertmanager-overview" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-alertmanager-overview namespace: monitoring - apiVersion: v1 data: apiserver.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "description": "The SLO (service level objective) and other metrics displayed on this dashboard are for informational purposes only.", "gridPos": { "h": 2, "w": 24, "x": 0, "y": 0 }, "id": 1, "options": { "content": "The SLO (service level objective) and other metrics displayed on this dashboard are for informational purposes only." }, "pluginVersion": "v11.4.0", "title": "Notice", "type": "text" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "description": "How many percent of requests (both read and write) in 30 days have been answered successfully and fast enough?", "fieldConfig": { "defaults": { "decimals": 3, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 2 }, "id": 2, "interval": "1m", "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "apiserver_request:availability30d{verb=\"all\", cluster=\"$cluster\"}" } ], "title": "Availability (30d) > 99.000%", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "description": "How much error budget is left looking at our 0.990% availability guarantees?", "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100 }, "decimals": 3, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 16, "x": 8, "y": 2 }, "id": 3, "interval": "1m", "options": { "legend": { "asTable": true, "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "100 * (apiserver_request:availability30d{verb=\"all\", cluster=\"$cluster\"} - 0.990000)", "legendFormat": "errorbudget" } ], "title": "ErrorBudget (30d) > 99.000%", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "description": "How many percent of read requests (LIST,GET) in 30 days have been answered successfully and fast enough?", "fieldConfig": { "defaults": { "decimals": 3, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 6, "x": 0, "y": 9 }, "id": 4, "interval": "1m", "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "apiserver_request:availability30d{verb=\"read\", cluster=\"$cluster\"}" } ], "title": "Read Availability (30d)", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "description": "How many read requests (LIST,GET) per second do the apiservers get by code?", "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "stacking": { "mode": "normal" } }, "unit": "reqps" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/2../i" }, "properties": [ { "id": "color", "value": "#56A64B" } ] }, { "matcher": { "id": "byRegexp", "options": "/3../i" }, "properties": [ { "id": "color", "value": "#F2CC0C" } ] }, { "matcher": { "id": "byRegexp", "options": "/4../i" }, "properties": [ { "id": "color", "value": "#3274D9" } ] }, { "matcher": { "id": "byRegexp", "options": "/5../i" }, "properties": [ { "id": "color", "value": "#E02F44" } ] } ] }, "gridPos": { "h": 7, "w": 6, "x": 6, "y": 9 }, "id": 5, "interval": "1m", "options": { "legend": { "asTable": true, "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (code) (code_resource:apiserver_request_total:rate5m{verb=\"read\", cluster=\"$cluster\"})", "legendFormat": "{{ code }}" } ], "title": "Read SLI - Requests", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "description": "How many percent of read requests (LIST,GET) per second are returned with errors (5xx)?", "fieldConfig": { "defaults": { "min": 0, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 6, "x": 12, "y": 9 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (resource) (code_resource:apiserver_request_total:rate5m{verb=\"read\",code=~\"5..\", cluster=\"$cluster\"}) / sum by (resource) (code_resource:apiserver_request_total:rate5m{verb=\"read\", cluster=\"$cluster\"})", "legendFormat": "{{ resource }}" } ], "title": "Read SLI - Errors", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "description": "How many seconds is the 99th percentile for reading (LIST|GET) a given resource?", "fieldConfig": { "defaults": { "unit": "s" } }, "gridPos": { "h": 7, "w": 6, "x": 18, "y": 9 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "cluster_quantile:apiserver_request_sli_duration_seconds:histogram_quantile{verb=\"read\", cluster=\"$cluster\"}", "legendFormat": "{{ resource }}" } ], "title": "Read SLI - Duration", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "description": "How many percent of write requests (POST|PUT|PATCH|DELETE) in 30 days have been answered successfully and fast enough?", "fieldConfig": { "defaults": { "decimals": 3, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 6, "x": 0, "y": 16 }, "id": 8, "interval": "1m", "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "apiserver_request:availability30d{verb=\"write\", cluster=\"$cluster\"}" } ], "title": "Write Availability (30d)", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "description": "How many write requests (POST|PUT|PATCH|DELETE) per second do the apiservers get by code?", "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "stacking": { "mode": "normal" } }, "unit": "reqps" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/2../i" }, "properties": [ { "id": "color", "value": "#56A64B" } ] }, { "matcher": { "id": "byRegexp", "options": "/3../i" }, "properties": [ { "id": "color", "value": "#F2CC0C" } ] }, { "matcher": { "id": "byRegexp", "options": "/4../i" }, "properties": [ { "id": "color", "value": "#3274D9" } ] }, { "matcher": { "id": "byRegexp", "options": "/5../i" }, "properties": [ { "id": "color", "value": "#E02F44" } ] } ] }, "gridPos": { "h": 7, "w": 6, "x": 6, "y": 16 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (code) (code_resource:apiserver_request_total:rate5m{verb=\"write\", cluster=\"$cluster\"})", "legendFormat": "{{ code }}" } ], "title": "Write SLI - Requests", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "description": "How many percent of write requests (POST|PUT|PATCH|DELETE) per second are returned with errors (5xx)?", "fieldConfig": { "defaults": { "min": 0, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 6, "x": 12, "y": 16 }, "id": 10, "interval": "1m", "options": { "legend": { "asTable": true, "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (resource) (code_resource:apiserver_request_total:rate5m{verb=\"write\",code=~\"5..\", cluster=\"$cluster\"}) / sum by (resource) (code_resource:apiserver_request_total:rate5m{verb=\"write\", cluster=\"$cluster\"})", "legendFormat": "{{ resource }}" } ], "title": "Write SLI - Errors", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "description": "How many seconds is the 99th percentile for writing (POST|PUT|PATCH|DELETE) a given resource?", "fieldConfig": { "defaults": { "unit": "s" } }, "gridPos": { "h": 7, "w": 6, "x": 18, "y": 16 }, "id": 11, "interval": "1m", "options": { "legend": { "asTable": true, "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "cluster_quantile:apiserver_request_sli_duration_seconds:histogram_quantile{verb=\"write\", cluster=\"$cluster\"}", "legendFormat": "{{ resource }}" } ], "title": "Write SLI - Duration", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "min": 0, "unit": "ops" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 23 }, "id": 12, "interval": "1m", "options": { "legend": { "asTable": true, "placement": "right", "showLegend": false }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(workqueue_adds_total{job=\"apiserver\", instance=~\"$instance\", cluster=\"$cluster\"}[$__rate_interval])) by (instance, name)", "legendFormat": "{{instance}} {{name}}" } ], "title": "Work Queue Add Rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "min": 0, "unit": "short" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 23 }, "id": 13, "interval": "1m", "options": { "legend": { "asTable": true, "placement": "right", "showLegend": false }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(workqueue_depth{job=\"apiserver\", instance=~\"$instance\", cluster=\"$cluster\"}[$__rate_interval])) by (instance, name)", "legendFormat": "{{instance}} {{name}}" } ], "title": "Work Queue Depth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "min": 0, "unit": "s" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 30 }, "id": 14, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(workqueue_queue_duration_seconds_bucket{job=\"apiserver\", instance=~\"$instance\", cluster=\"$cluster\"}[$__rate_interval])) by (instance, name, le))", "legendFormat": "{{instance}} {{name}}" } ], "title": "Work Queue Latency", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "bytes" } }, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 37 }, "id": 15, "interval": "1m", "options": { "legend": { "asTable": true, "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "process_resident_memory_bytes{job=\"apiserver\",instance=~\"$instance\", cluster=\"$cluster\"}", "legendFormat": "{{instance}}" } ], "title": "Memory", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "min": 0, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 8, "y": 37 }, "id": 16, "interval": "1m", "options": { "legend": { "asTable": true, "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "rate(process_cpu_seconds_total{job=\"apiserver\",instance=~\"$instance\", cluster=\"$cluster\"}[$__rate_interval])", "legendFormat": "{{instance}}" } ], "title": "CPU usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 16, "y": 37 }, "id": 17, "interval": "1m", "options": { "legend": { "asTable": true, "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "go_goroutines{job=\"apiserver\",instance=~\"$instance\", cluster=\"$cluster\"}", "legendFormat": "{{instance}}" } ], "title": "Goroutines", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"apiserver\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "name": "instance", "query": "label_values(up{job=\"apiserver\", cluster=\"$cluster\"}, instance)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / API server", "uid": "09ec8aa1e996d6ffcd6817bbaff4db1b" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-apiserver namespace: monitoring - apiVersion: v1 data: cluster-total.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "binBps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Current Rate of Bytes Received", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "binBps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 0 }, "id": 2, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Current Rate of Bytes Transmitted", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/Bytes/" }, "properties": [ { "id": "unit", "value": "binBps" } ] }, { "matcher": { "id": "byRegexp", "options": "/Packets/" }, "properties": [ { "id": "unit", "value": "pps" } ] }, { "matcher": { "id": "byName", "options": "Namespace" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down", "url": "/d/8b7a8b326d7a6f1f04244066368c67af/kubernetes-networking-namespace-pods?${datasource:queryparam}&var-cluster=${cluster}&var-namespace=${__data.fields.Namespace}" } ] } ] } ] }, "gridPos": { "h": 9, "w": 24, "x": 0, "y": 9 }, "id": 3, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "avg by (namespace) (\n rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "avg by (namespace) (\n rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_receive_packets_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true } ], "title": "Current Status", "transformations": [ { "id": "joinByField", "options": { "byField": "namespace", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true, "Time 7": true, "Time 8": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Time 7": 6, "Time 8": 7, "Value #A": 9, "Value #B": 10, "Value #C": 11, "Value #D": 12, "Value #E": 13, "Value #F": 14, "Value #G": 15, "Value #H": 16, "namespace": 8 }, "renameByName": { "Value #A": "Rx Bytes", "Value #B": "Tx Bytes", "Value #C": "Rx Bytes (Avg)", "Value #D": "Tx Bytes (Avg)", "Value #E": "Rx Packets", "Value #F": "Tx Packets", "Value #G": "Rx Packets Dropped", "Value #H": "Tx Packets Dropped", "namespace": "Namespace" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "binBps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 18 }, "id": 4, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "avg by (namespace) (\n rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Average Rate of Bytes Received", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "binBps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 18 }, "id": 5, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "avg by (namespace) (\n rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Average Rate of Bytes Transmitted", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "binBps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 27 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Receive Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "binBps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 27 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Transmit Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 36 }, "id": 8, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_receive_packets_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Rate of Received Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 36 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 45 }, "id": 10, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Rate of Received Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 45 }, "id": 11, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (namespace) (\n rate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "percentunit" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 54 }, "id": 12, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (instance) (\n rate(node_netstat_Tcp_RetransSegs{cluster=\"$cluster\"}[$__rate_interval]) / rate(node_netstat_Tcp_OutSegs{cluster=\"$cluster\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Rate of TCP Retransmits out of all sent segments", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "percentunit" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 54 }, "id": 13, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (instance) (\n rate(node_netstat_TcpExt_TCPSynRetrans{cluster=\"$cluster\"}[$__rate_interval]) / rate(node_netstat_Tcp_RetransSegs{cluster=\"$cluster\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Rate of TCP SYN Retransmits out of all retransmits", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Networking / Cluster", "uid": "ff635a025bcfea7bc3dd4f508990a3e9" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-cluster-total namespace: monitoring - apiVersion: v1 data: controller-manager.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "none" } }, "gridPos": { "h": 7, "w": 4, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(up{cluster=\"$cluster\", job=\"kube-controller-manager\"})", "instant": true } ], "title": "Up", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 20, "x": 4, "y": 0 }, "id": 2, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(workqueue_adds_total{cluster=\"$cluster\", job=\"kube-controller-manager\", instance=~\"$instance\"}[$__rate_interval])) by (cluster, instance, name)", "legendFormat": "{{cluster}} {{instance}} {{name}}" } ], "title": "Work Queue Add Rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "short" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 7 }, "id": 3, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(workqueue_depth{cluster=\"$cluster\", job=\"kube-controller-manager\", instance=~\"$instance\"}[$__rate_interval])) by (cluster, instance, name)", "legendFormat": "{{cluster}} {{instance}} {{name}}" } ], "title": "Work Queue Depth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 14 }, "id": 4, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(workqueue_queue_duration_seconds_bucket{cluster=\"$cluster\", job=\"kube-controller-manager\", instance=~\"$instance\"}[$__rate_interval])) by (cluster, instance, name, le))", "legendFormat": "{{cluster}} {{instance}} {{name}}" } ], "title": "Work Queue Latency", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 21 }, "id": 5, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{job=\"kube-controller-manager\", instance=~\"$instance\",code=~\"2..\"}[$__rate_interval]))", "legendFormat": "2xx" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{job=\"kube-controller-manager\", instance=~\"$instance\",code=~\"3..\"}[$__rate_interval]))", "legendFormat": "3xx" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{job=\"kube-controller-manager\", instance=~\"$instance\",code=~\"4..\"}[$__rate_interval]))", "legendFormat": "4xx" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{job=\"kube-controller-manager\", instance=~\"$instance\",code=~\"5..\"}[$__rate_interval]))", "legendFormat": "5xx" } ], "title": "Kube API Request Rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 16, "x": 8, "y": 21 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\"$cluster\", job=\"kube-controller-manager\", instance=~\"$instance\", verb=\"POST\"}[$__rate_interval])) by (verb, le))", "legendFormat": "{{verb}}" } ], "title": "Post Request Latency 99th Quantile", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 28 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\"$cluster\", job=\"kube-controller-manager\", instance=~\"$instance\", verb=\"GET\"}[$__rate_interval])) by (verb, le))", "legendFormat": "{{verb}}" } ], "title": "Get Request Latency 99th Quantile", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "bytes" } }, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 35 }, "id": 8, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "process_resident_memory_bytes{cluster=\"$cluster\", job=\"kube-controller-manager\",instance=~\"$instance\"}", "legendFormat": "{{instance}}" } ], "title": "Memory", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 8, "y": 35 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "rate(process_cpu_seconds_total{cluster=\"$cluster\", job=\"kube-controller-manager\",instance=~\"$instance\"}[$__rate_interval])", "legendFormat": "{{instance}}" } ], "title": "CPU usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 16, "y": 35 }, "id": 10, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "go_goroutines{cluster=\"$cluster\", job=\"kube-controller-manager\",instance=~\"$instance\"}", "legendFormat": "{{instance}}" } ], "title": "Goroutines", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kube-controller-manager\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "label": "instance", "name": "instance", "query": "label_values(up{cluster=\"$cluster\", job=\"kube-controller-manager\"}, instance)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Controller Manager", "uid": "72e0e05bef5099e5f049b05fdc429ed4" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-controller-manager namespace: monitoring - apiVersion: v1 data: grafana-overview.json: |- { "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": true, "gnetId": null, "graphTooltip": 0, "id": 3085, "iteration": 1631554945276, "links": [ ], "panels": [ { "datasource": "$datasource", "fieldConfig": { "defaults": { "mappings": [ ], "noValue": "0", "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [ ] }, "gridPos": { "h": 5, "w": 6, "x": 0, "y": 0 }, "id": 6, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "mean" ], "fields": "", "values": false }, "text": { }, "textMode": "auto" }, "pluginVersion": "8.1.3", "targets": [ { "expr": "grafana_alerting_result_total{job=~\"$job\", instance=~\"$instance\", state=\"alerting\"}", "instant": true, "interval": "", "legendFormat": "", "refId": "A" } ], "timeFrom": null, "timeShift": null, "title": "Firing Alerts", "type": "stat" }, { "datasource": "$datasource", "fieldConfig": { "defaults": { "mappings": [ ], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [ ] }, "gridPos": { "h": 5, "w": 6, "x": 6, "y": 0 }, "id": 8, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "mean" ], "fields": "", "values": false }, "text": { }, "textMode": "auto" }, "pluginVersion": "8.1.3", "targets": [ { "expr": "sum(grafana_stat_totals_dashboard{job=~\"$job\", instance=~\"$instance\"})", "interval": "", "legendFormat": "", "refId": "A" } ], "timeFrom": null, "timeShift": null, "title": "Dashboards", "type": "stat" }, { "datasource": "$datasource", "fieldConfig": { "defaults": { "custom": { "align": null, "displayMode": "auto" }, "mappings": [ ], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [ ] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 0 }, "id": 10, "options": { "showHeader": true }, "pluginVersion": "8.1.3", "targets": [ { "expr": "grafana_build_info{job=~\"$job\", instance=~\"$instance\"}", "instant": true, "interval": "", "legendFormat": "", "refId": "A" } ], "timeFrom": null, "timeShift": null, "title": "Build Info", "transformations": [ { "id": "labelsToFields", "options": { } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Value": true, "branch": true, "container": true, "goversion": true, "namespace": true, "pod": true, "revision": true }, "indexByName": { "Time": 7, "Value": 11, "branch": 4, "container": 8, "edition": 2, "goversion": 6, "instance": 1, "job": 0, "namespace": 9, "pod": 10, "revision": 5, "version": 3 }, "renameByName": { } } } ], "type": "table" }, { "aliasColors": { }, "bars": false, "dashLength": 10, "dashes": false, "datasource": "$datasource", "fieldConfig": { "defaults": { "links": [ ] }, "overrides": [ ] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 5 }, "hiddenSeries": false, "id": 2, "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.1.3", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [ ], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "expr": "sum by (status_code) (irate(grafana_http_request_duration_seconds_count{job=~\"$job\", instance=~\"$instance\"}[1m])) ", "interval": "", "legendFormat": "{{status_code}}", "refId": "A" } ], "thresholds": [ ], "timeFrom": null, "timeRegions": [ ], "timeShift": null, "title": "RPS", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [ ] }, "yaxes": [ { "$$hashKey": "object:157", "format": "reqps", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "$$hashKey": "object:158", "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": "$datasource", "fieldConfig": { "defaults": { "links": [ ] }, "overrides": [ ] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 5 }, "hiddenSeries": false, "id": 4, "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.1.3", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [ ], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "exemplar": true, "expr": "histogram_quantile(0.99, sum(irate(grafana_http_request_duration_seconds_bucket{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval])) by (le)) * 1", "interval": "", "legendFormat": "99th Percentile", "refId": "A" }, { "exemplar": true, "expr": "histogram_quantile(0.50, sum(irate(grafana_http_request_duration_seconds_bucket{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval])) by (le)) * 1", "interval": "", "legendFormat": "50th Percentile", "refId": "B" }, { "exemplar": true, "expr": "sum(irate(grafana_http_request_duration_seconds_sum{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval])) * 1 / sum(irate(grafana_http_request_duration_seconds_count{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval]))", "interval": "", "legendFormat": "Average", "refId": "C" } ], "thresholds": [ ], "timeFrom": null, "timeRegions": [ ], "timeShift": null, "title": "Request Latency", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [ ] }, "yaxes": [ { "$$hashKey": "object:210", "format": "ms", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "$$hashKey": "object:211", "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } } ], "schemaVersion": 30, "tags": [ ], "templating": { "list": [ { "current": { "selected": true, "text": "dev-cortex", "value": "dev-cortex" }, "description": null, "error": null, "hide": 0, "includeAll": false, "label": null, "multi": false, "name": "datasource", "options": [ ], "query": "prometheus", "queryValue": "", "refresh": 1, "regex": "", "skipUrlSync": false, "type": "datasource" }, { "allValue": ".*", "current": { "selected": false, "text": [ "default/grafana" ], "value": [ "default/grafana" ] }, "datasource": "$datasource", "definition": "label_values(grafana_build_info, job)", "description": null, "error": null, "hide": 0, "includeAll": true, "label": null, "multi": true, "name": "job", "options": [ ], "query": { "query": "label_values(grafana_build_info, job)", "refId": "Billing Admin-job-Variable-Query" }, "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 0, "tagValuesQuery": "", "tagsQuery": "", "type": "query", "useTags": false }, { "allValue": ".*", "current": { "selected": false, "text": "All", "value": "$__all" }, "datasource": "$datasource", "definition": "label_values(grafana_build_info, instance)", "description": null, "error": null, "hide": 0, "includeAll": true, "label": null, "multi": true, "name": "instance", "options": [ ], "query": { "query": "label_values(grafana_build_info, instance)", "refId": "Billing Admin-instance-Variable-Query" }, "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 0, "tagValuesQuery": "", "tagsQuery": "", "type": "query", "useTags": false } ] }, "time": { "from": "now-6h", "to": "now" }, "timepicker": { "refresh_intervals": [ "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d" ] }, "timezone": "", "title": "Grafana Overview", "uid": "6be0s85Mk", "version": 2 } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-grafana-overview namespace: monitoring - apiVersion: v1 data: k8s-resources-cluster.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "cluster:node_cpu:ratio_rate5m{cluster=\"$cluster\"}", "instant": true } ], "title": "CPU Utilisation", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 4, "y": 0 }, "id": 2, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_cpu:kube_pod_container_resource_requests:sum{cluster=\"$cluster\"}) / sum(kube_node_status_allocatable{job=\"kube-state-metrics\",resource=\"cpu\",cluster=\"$cluster\"})", "instant": true } ], "title": "CPU Requests Commitment", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 8, "y": 0 }, "id": 3, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_cpu:kube_pod_container_resource_limits:sum{cluster=\"$cluster\"}) / sum(kube_node_status_allocatable{job=\"kube-state-metrics\",resource=\"cpu\",cluster=\"$cluster\"})", "instant": true } ], "title": "CPU Limits Commitment", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 12, "y": 0 }, "id": 4, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "1 - sum(:node_memory_MemAvailable_bytes:sum{cluster=\"$cluster\"}) / sum(node_memory_MemTotal_bytes{job=\"node-exporter\",cluster=\"$cluster\"})", "instant": true } ], "title": "Memory Utilisation", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 16, "y": 0 }, "id": 5, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_memory:kube_pod_container_resource_requests:sum{cluster=\"$cluster\"}) / sum(kube_node_status_allocatable{job=\"kube-state-metrics\",resource=\"memory\",cluster=\"$cluster\"})", "instant": true } ], "title": "Memory Requests Commitment", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 20, "y": 0 }, "id": 6, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_memory:kube_pod_container_resource_limits:sum{cluster=\"$cluster\"}) / sum(kube_node_status_allocatable{job=\"kube-state-metrics\",resource=\"memory\",cluster=\"$cluster\"})", "instant": true } ], "title": "Memory Limits Commitment", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true } } }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 6 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\"}) by (namespace)", "legendFormat": "__auto" } ], "title": "CPU Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Namespace" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?${datasource:queryparam}&var-cluster=$cluster&var-namespace=${__data.fields.Namespace}" } ] } ] } ] }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 12 }, "id": 8, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_owner{job=\"kube-state-metrics\", cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "count(avg(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\"}) by (workload, namespace)) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_cpu:kube_pod_container_resource_requests:sum{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\"}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_requests:sum{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_cpu:kube_pod_container_resource_limits:sum{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\"}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_limits:sum{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true } ], "title": "CPU Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "namespace", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true, "Time 7": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Time 7": 6, "Value #A": 8, "Value #B": 9, "Value #C": 10, "Value #D": 11, "Value #E": 12, "Value #F": 13, "Value #G": 14, "namespace": 7 }, "renameByName": { "Value #A": "Pods", "Value #B": "Workloads", "Value #C": "CPU Usage", "Value #D": "CPU Requests", "Value #E": "CPU Requests %", "Value #F": "CPU Limits", "Value #G": "CPU Limits %", "namespace": "Namespace" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "bytes" } }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 18 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_rss{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", container!=\"\"}) by (namespace)", "legendFormat": "__auto" } ], "title": "Memory", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Memory Usage" }, "properties": [ { "id": "unit", "value": "bytes" } ] }, { "matcher": { "id": "byName", "options": "Memory Requests" }, "properties": [ { "id": "unit", "value": "bytes" } ] }, { "matcher": { "id": "byName", "options": "Memory Limits" }, "properties": [ { "id": "unit", "value": "bytes" } ] }, { "matcher": { "id": "byName", "options": "Namespace" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?${datasource:queryparam}&var-cluster=$cluster&var-namespace=${__data.fields.Namespace}" } ] } ] } ] }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 24 }, "id": 10, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_owner{job=\"kube-state-metrics\", cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "count(avg(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\"}) by (workload, namespace)) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_rss{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", container!=\"\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_memory:kube_pod_container_resource_requests:sum{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_rss{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", container!=\"\"}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_requests:sum{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_memory:kube_pod_container_resource_limits:sum{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_rss{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", container!=\"\"}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_limits:sum{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true } ], "title": "Memory Requests by Namespace", "transformations": [ { "id": "joinByField", "options": { "byField": "namespace", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true, "Time 7": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Time 7": 6, "Value #A": 8, "Value #B": 9, "Value #C": 10, "Value #D": 11, "Value #E": 12, "Value #F": 13, "Value #G": 14, "namespace": 7 }, "renameByName": { "Value #A": "Pods", "Value #B": "Workloads", "Value #C": "Memory Usage", "Value #D": "Memory Requests", "Value #E": "Memory Requests %", "Value #F": "Memory Limits", "Value #G": "Memory Limits %", "namespace": "Namespace" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/Bandwidth/" }, "properties": [ { "id": "unit", "value": "Bps" } ] }, { "matcher": { "id": "byRegexp", "options": "/Packets/" }, "properties": [ { "id": "unit", "value": "pps" } ] }, { "matcher": { "id": "byName", "options": "Namespace" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?${datasource:queryparam}&var-cluster=$cluster&var-namespace=${__data.fields.Namespace}" } ] } ] } ] }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 30 }, "id": 11, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "format": "table", "instant": true } ], "title": "Current Network Usage", "transformations": [ { "id": "joinByField", "options": { "byField": "namespace", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Value #A": 7, "Value #B": 8, "Value #C": 9, "Value #D": 10, "Value #E": 11, "Value #F": 12, "namespace": 6 }, "renameByName": { "Value #A": "Current Receive Bandwidth", "Value #B": "Current Transmit Bandwidth", "Value #C": "Rate of Received Packets", "Value #D": "Rate of Transmitted Packets", "Value #E": "Rate of Received Packets Dropped", "Value #F": "Rate of Transmitted Packets Dropped", "namespace": "Namespace" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 36 }, "id": 12, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "legendFormat": "__auto" } ], "title": "Receive Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 42 }, "id": 13, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "legendFormat": "__auto" } ], "title": "Transmit Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 48 }, "id": 14, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "avg(irate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "legendFormat": "__auto" } ], "title": "Average Container Bandwidth by Namespace: Received", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 54 }, "id": 15, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "avg(irate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "legendFormat": "__auto" } ], "title": "Average Container Bandwidth by Namespace: Transmitted", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 60 }, "id": 16, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(irate(container_network_receive_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "legendFormat": "__auto" } ], "title": "Rate of Received Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 66 }, "id": 17, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(irate(container_network_transmit_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 72 }, "id": 18, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(irate(container_network_receive_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "legendFormat": "__auto" } ], "title": "Rate of Received Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 78 }, "id": 19, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(irate(container_network_transmit_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "iops" } }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 84 }, "id": 20, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "ceil(sum by(namespace) (rate(container_fs_reads_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", cluster=\"$cluster\", namespace!=\"\"}[$__rate_interval]) + rate(container_fs_writes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", container!=\"\", cluster=\"$cluster\", namespace!=\"\"}[$__rate_interval])))", "legendFormat": "__auto" } ], "title": "IOPS(Reads+Writes)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 90 }, "id": 21, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(namespace) (rate(container_fs_reads_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", cluster=\"$cluster\", namespace!=\"\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", container!=\"\", cluster=\"$cluster\", namespace!=\"\"}[$__rate_interval]))", "legendFormat": "__auto" } ], "title": "ThroughPut(Read+Write)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/IOPS/" }, "properties": [ { "id": "unit", "value": "iops" } ] }, { "matcher": { "id": "byRegexp", "options": "/Throughput/" }, "properties": [ { "id": "unit", "value": "Bps" } ] }, { "matcher": { "id": "byName", "options": "Namespace" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?${datasource:queryparam}&var-cluster=$cluster&var-namespace=${__data.fields.Namespace}" } ] } ] } ] }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 96 }, "id": 22, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(namespace) (rate(container_fs_reads_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace!=\"\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(namespace) (rate(container_fs_writes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace!=\"\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(namespace) (rate(container_fs_reads_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace!=\"\"}[$__rate_interval]) + rate(container_fs_writes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace!=\"\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(namespace) (rate(container_fs_reads_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace!=\"\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(namespace) (rate(container_fs_writes_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace!=\"\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(namespace) (rate(container_fs_reads_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace!=\"\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace!=\"\"}[$__rate_interval]))", "format": "table", "instant": true } ], "title": "Current Storage IO", "transformations": [ { "id": "joinByField", "options": { "byField": "namespace", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Value #A": 7, "Value #B": 8, "Value #C": 9, "Value #D": 10, "Value #E": 11, "Value #F": 12, "namespace": 6 }, "renameByName": { "Value #A": "IOPS(Reads)", "Value #B": "IOPS(Writes)", "Value #C": "IOPS(Reads + Writes)", "Value #D": "Throughput(Read)", "Value #E": "Throughput(Write)", "Value #F": "Throughput(Read + Write)", "namespace": "Namespace" } } } ], "type": "table" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Compute Resources / Cluster", "uid": "efa86fd1d0c121a26444b636a3f509a8" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-k8s-resources-cluster namespace: monitoring - apiVersion: v1 data: k8s-resources-multicluster.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "none" } }, "gridPos": { "h": 3, "w": 4, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(cluster:node_cpu:ratio_rate5m) / count(cluster:node_cpu:ratio_rate5m)", "instant": true } ], "title": "CPU Utilisation", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 4, "y": 0 }, "id": 2, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_container_resource_requests{job=\"kube-state-metrics\", resource=\"cpu\"}) / sum(kube_node_status_allocatable{job=\"kube-state-metrics\", resource=\"cpu\"})", "instant": true } ], "title": "CPU Requests Commitment", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 8, "y": 0 }, "id": 3, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_container_resource_limits{job=\"kube-state-metrics\", resource=\"cpu\"}) / sum(kube_node_status_allocatable{job=\"kube-state-metrics\", resource=\"cpu\"})", "instant": true } ], "title": "CPU Limits Commitment", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 12, "y": 0 }, "id": 4, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "1 - sum(:node_memory_MemAvailable_bytes:sum) / sum(node_memory_MemTotal_bytes{job=\"node-exporter\"})", "instant": true } ], "title": "Memory Utilisation", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 16, "y": 0 }, "id": 5, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_container_resource_requests{job=\"kube-state-metrics\", resource=\"memory\"}) / sum(kube_node_status_allocatable{job=\"kube-state-metrics\", resource=\"memory\"})", "instant": true } ], "title": "Memory Requests Commitment", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 20, "y": 0 }, "id": 6, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_container_resource_limits{job=\"kube-state-metrics\", resource=\"memory\"}) / sum(kube_node_status_allocatable{job=\"kube-state-metrics\", resource=\"memory\"})", "instant": true } ], "title": "Memory Limits Commitment", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" } } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 1 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m) by (cluster)", "legendFormat": "__auto" } ], "title": "CPU Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Cluster" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down", "url": "/d/efa86fd1d0c121a26444b636a3f509a8/kubernetes-compute-resources-cluster?${datasource:queryparam}&var-cluster=${__data.fields.Cluster}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 2 }, "id": 8, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m) by (cluster)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_container_resource_requests{job=\"kube-state-metrics\", resource=\"cpu\"}) by (cluster)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m) by (cluster) / sum(kube_pod_container_resource_requests{job=\"kube-state-metrics\", resource=\"cpu\"}) by (cluster)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_container_resource_limits{job=\"kube-state-metrics\", resource=\"cpu\"}) by (cluster)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m) by (cluster) / sum(kube_pod_container_resource_limits{job=\"kube-state-metrics\", resource=\"cpu\"}) by (cluster)", "format": "table", "instant": true } ], "title": "CPU Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "cluster", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Value #A": 6, "Value #B": 7, "Value #C": 8, "Value #D": 9, "Value #E": 10, "cluster": 5 }, "renameByName": { "Value #A": "CPU Usage", "Value #B": "CPU Requests", "Value #C": "CPU Requests %", "Value #D": "CPU Limits", "Value #E": "CPU Limits %", "cluster": "Cluster" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "bytes" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 3 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_rss{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", container!=\"\"}) by (cluster)", "legendFormat": "__auto" } ], "title": "Memory Usage (w/o cache)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Cluster" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down", "url": "/d/efa86fd1d0c121a26444b636a3f509a8/kubernetes-compute-resources-cluster?${datasource:queryparam}&var-cluster=${__data.fields.Cluster}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 4 }, "id": 10, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_rss{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", container!=\"\"}) by (cluster)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_container_resource_requests{job=\"kube-state-metrics\", resource=\"memory\"}) by (cluster)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_rss{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", container!=\"\"}) by (cluster) / sum(kube_pod_container_resource_requests{job=\"kube-state-metrics\", resource=\"memory\"}) by (cluster)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_container_resource_limits{job=\"kube-state-metrics\", resource=\"memory\"}) by (cluster)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_rss{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", container!=\"\"}) by (cluster) / sum(kube_pod_container_resource_limits{job=\"kube-state-metrics\", resource=\"memory\"}) by (cluster)", "format": "table", "instant": true } ], "title": "Memory Requests by Cluster", "transformations": [ { "id": "joinByField", "options": { "byField": "cluster", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Value #A": 6, "Value #B": 7, "Value #C": 8, "Value #D": 9, "Value #E": 10, "cluster": 5 }, "renameByName": { "Value #A": "Memory Usage", "Value #B": "Memory Requests", "Value #C": "Memory Requests %", "Value #D": "Memory Limits", "Value #E": "Memory Limits %", "cluster": "Cluster" } } } ], "type": "table" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Compute Resources / Multi-Cluster", "uid": "b59e6c9f2fcbe2e16d77fc492374cc4f" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-k8s-resources-multicluster namespace: monitoring - apiVersion: v1 data: k8s-resources-namespace.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 6, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}) / sum(kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"cpu\"})", "instant": true } ], "title": "CPU Utilisation (from requests)", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 6, "x": 6, "y": 0 }, "id": 2, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}) / sum(kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"cpu\"})", "instant": true } ], "title": "CPU Utilisation (from limits)", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 6, "x": 12, "y": 0 }, "id": 3, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\", image!=\"\"}) / sum(kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"memory\"})", "instant": true } ], "title": "Memory Utilisation (from requests)", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 6, "x": 18, "y": 0 }, "id": 4, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\", image!=\"\"}) / sum(kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"memory\"})", "instant": true } ], "title": "Memory Utilisation (from limits)", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true } }, "overrides": [ { "matcher": { "id": "byFrameRefID", "options": "B" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash" } }, { "id": "custom.lineWidth", "value": 2 }, { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byFrameRefID", "options": "C" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash" } }, { "id": "custom.lineWidth", "value": 2 }, { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 7 }, "id": 5, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "legendFormat": "__auto" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "scalar(max(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=\"requests.cpu\"}))", "legendFormat": "quota - requests" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "scalar(max(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=\"limits.cpu\"}))", "legendFormat": "quota - limits" } ], "title": "CPU Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Pod" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-pod=${__data.fields.Pod}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 14 }, "id": 6, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true } ], "title": "CPU Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "pod", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Value #A": 6, "Value #B": 7, "Value #C": 8, "Value #D": 9, "Value #E": 10, "pod": 5 }, "renameByName": { "Value #A": "CPU Usage", "Value #B": "CPU Requests", "Value #C": "CPU Requests %", "Value #D": "CPU Limits", "Value #E": "CPU Limits %", "pod": "Pod" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byFrameRefID", "options": "B" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash" } }, { "id": "custom.lineWidth", "value": 2 }, { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byFrameRefID", "options": "C" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash" } }, { "id": "custom.lineWidth", "value": 2 }, { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 21 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}) by (pod)", "legendFormat": "__auto" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "scalar(max(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=\"requests.memory\"}))", "legendFormat": "quota - requests" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "scalar(max(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=\"limits.memory\"}))", "legendFormat": "quota - limits" } ], "title": "Memory Usage (w/o cache)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Pod" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-pod=${__data.fields.Pod}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 28 }, "id": 8, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_rss{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_cache{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_swap{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\"}) by (pod)", "format": "table", "instant": true } ], "title": "Memory Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "pod", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true, "Time 7": true, "Time 8": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Time 7": 6, "Time 8": 7, "Value #A": 9, "Value #B": 10, "Value #C": 11, "Value #D": 12, "Value #E": 13, "Value #F": 14, "Value #G": 15, "Value #H": 16, "pod": 8 }, "renameByName": { "Value #A": "Memory Usage", "Value #B": "Memory Requests", "Value #C": "Memory Requests %", "Value #D": "Memory Limits", "Value #E": "Memory Limits %", "Value #F": "Memory Usage (RSS)", "Value #G": "Memory Usage (Cache)", "Value #H": "Memory Usage (Swap)", "pod": "Pod" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/Bandwidth/" }, "properties": [ { "id": "unit", "value": "Bps" } ] }, { "matcher": { "id": "byRegexp", "options": "/Packets/" }, "properties": [ { "id": "unit", "value": "pps" } ] }, { "matcher": { "id": "byName", "options": "Pod" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-pod=${__data.fields.Pod}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 35 }, "id": 9, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)", "format": "table", "instant": true } ], "title": "Current Network Usage", "transformations": [ { "id": "joinByField", "options": { "byField": "pod", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Value #A": 7, "Value #B": 8, "Value #C": 9, "Value #D": 10, "Value #E": 11, "Value #F": 12, "pod": 6 }, "renameByName": { "Value #A": "Current Receive Bandwidth", "Value #B": "Current Transmit Bandwidth", "Value #C": "Rate of Received Packets", "Value #D": "Rate of Transmitted Packets", "Value #E": "Rate of Received Packets Dropped", "Value #F": "Rate of Transmitted Packets Dropped", "pod": "Pod" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 42 }, "id": 10, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Receive Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 42 }, "id": 11, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Transmit Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 49 }, "id": 12, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(irate(container_network_receive_packets_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Rate of Received Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 49 }, "id": 13, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 56 }, "id": 14, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Rate of Received Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 56 }, "id": 15, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "iops" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 63 }, "id": 16, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "ceil(sum by(pod) (rate(container_fs_reads_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])))", "legendFormat": "__auto" } ], "title": "IOPS(Reads+Writes)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 63 }, "id": 17, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]))", "legendFormat": "__auto" } ], "title": "ThroughPut(Read+Write)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/IOPS/" }, "properties": [ { "id": "unit", "value": "iops" } ] }, { "matcher": { "id": "byRegexp", "options": "/Throughput/" }, "properties": [ { "id": "unit", "value": "Bps" } ] }, { "matcher": { "id": "byName", "options": "Pod" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-pod=${__data.fields.Pod}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 70 }, "id": 18, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(pod) (rate(container_fs_reads_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(pod) (rate(container_fs_writes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(pod) (rate(container_fs_reads_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(pod) (rate(container_fs_writes_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval]))", "format": "table", "instant": true } ], "title": "Current Storage IO", "transformations": [ { "id": "joinByField", "options": { "byField": "pod", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Value #A": 7, "Value #B": 8, "Value #C": 9, "Value #D": 10, "Value #E": 11, "Value #F": 12, "pod": 6 }, "renameByName": { "Value #A": "IOPS(Reads)", "Value #B": "IOPS(Writes)", "Value #C": "IOPS(Reads + Writes)", "Value #D": "Throughput(Read)", "Value #E": "Throughput(Write)", "Value #F": "Throughput(Read + Write)", "pod": "Pod" } } } ], "type": "table" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kube-state-metrics\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "namespace", "name": "namespace", "query": "label_values(kube_namespace_status_phase{job=\"kube-state-metrics\", cluster=\"$cluster\"}, namespace)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Compute Resources / Namespace (Pods)", "uid": "85a562078cdf77779eaa1add43ccec1e" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-k8s-resources-namespace namespace: monitoring - apiVersion: v1 data: k8s-resources-node.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true, "stacking": { "mode": "normal" } } }, "overrides": [ { "matcher": { "id": "byName", "options": "max capacity" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } }, { "id": "custom.stacking", "value": { "mode": "none" } }, { "id": "custom.hideFrom", "value": { "legend": false, "tooltip": true, "viz": false } }, { "id": "custom.lineStyle", "value": { "dash": [ 10, 10 ], "fill": "dash" } } ] } ] }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_node_status_capacity{cluster=\"$cluster\", job=\"kube-state-metrics\", node=~\"$node\", resource=\"cpu\"})", "legendFormat": "max capacity" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", "legendFormat": "{{pod}}" } ], "title": "CPU Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Pod" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-pod=${__data.fields.Pod}" } ] } ] } ] }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 6 }, "id": 2, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", node=~\"$node\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", node=~\"$node\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", "format": "table", "instant": true } ], "title": "CPU Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "pod", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true }, "renameByName": { "Value #A": "CPU Usage", "Value #B": "CPU Requests", "Value #C": "CPU Requests %", "Value #D": "CPU Limits", "Value #E": "CPU Limits %", "pod": "Pod" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true, "stacking": { "mode": "normal" } }, "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byName", "options": "max capacity" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } }, { "id": "custom.stacking", "value": { "mode": "none" } }, { "id": "custom.hideFrom", "value": { "legend": false, "tooltip": true, "viz": false } }, { "id": "custom.lineStyle", "value": { "dash": [ 10, 10 ], "fill": "dash" } } ] } ] }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 12 }, "id": 3, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_node_status_capacity{cluster=\"$cluster\", job=\"kube-state-metrics\", node=~\"$node\", resource=\"memory\"})", "legendFormat": "max capacity" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\", container!=\"\"}) by (pod)", "legendFormat": "{{pod}}" } ], "title": "Memory Usage (w/cache)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true, "stacking": { "mode": "normal" } }, "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byName", "options": "max capacity" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } }, { "id": "custom.stacking", "value": { "mode": "none" } }, { "id": "custom.hideFrom", "value": { "legend": false, "tooltip": true, "viz": false } }, { "id": "custom.lineStyle", "value": { "dash": [ 10, 10 ], "fill": "dash" } } ] } ] }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 18 }, "id": 4, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_node_status_capacity{cluster=\"$cluster\", job=\"kube-state-metrics\", node=~\"$node\", resource=\"memory\"})", "legendFormat": "max capacity" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_memory_rss{cluster=\"$cluster\", node=~\"$node\", container!=\"\"}) by (pod)", "legendFormat": "{{pod}}" } ], "title": "Memory Usage (w/o cache)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Pod" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-pod=${__data.fields.Pod}" } ] } ] } ] }, "gridPos": { "h": 6, "w": 24, "x": 0, "y": 24 }, "id": 5, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_memory_rss{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_memory_cache{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_memory_swap{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod)", "format": "table", "instant": true } ], "title": "Memory Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "pod", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true, "Time 7": true, "Time 8": true }, "renameByName": { "Value #A": "Memory Usage", "Value #B": "Memory Requests", "Value #C": "Memory Requests %", "Value #D": "Memory Limits", "Value #E": "Memory Limits %", "Value #F": "Memory Usage (RSS)", "Value #G": "Memory Usage (Cache)", "Value #H": "Memory Usage (Swap)", "pod": "Pod" } } } ], "type": "table" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kube-state-metrics\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "node", "multi": true, "name": "node", "query": "label_values(kube_node_info{cluster=\"$cluster\"}, node)", "refresh": 2, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Compute Resources / Node (Pods)", "uid": "200ac8fdbfbb74b39aff88118e4d1c2c" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-k8s-resources-node namespace: monitoring - apiVersion: v1 data: k8s-resources-pod.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true } }, "overrides": [ { "matcher": { "id": "byFrameRefID", "options": "B" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash" } }, { "id": "custom.lineWidth", "value": 2 }, { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byFrameRefID", "options": "C" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash" } }, { "id": "custom.lineWidth", "value": 2 }, { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{namespace=\"$namespace\", pod=\"$pod\", cluster=\"$cluster\", container!=\"\"}) by (container)", "legendFormat": "__auto" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"}\n)\n", "legendFormat": "requests" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"}\n)\n", "legendFormat": "limits" } ], "title": "CPU Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "axisColorMode": "thresholds", "axisSoftMax": 1, "axisSoftMin": 0, "fillOpacity": 10, "showPoints": "never", "spanNulls": true, "thresholdsStyle": { "mode": "dashed+area" } }, "unit": "percentunit" }, "overrides": [ { "matcher": { "id": "byFrameRefID", "options": "A" }, "properties": [ { "id": "thresholds", "value": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 0.25 } ] } }, { "id": "color", "value": { "mode": "thresholds", "seriesBy": "lastNotNull" } } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 7 }, "id": 2, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(increase(container_cpu_cfs_throttled_periods_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\", cluster=\"$cluster\"}[$__rate_interval])) by (container) /sum(increase(container_cpu_cfs_periods_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\", cluster=\"$cluster\"}[$__rate_interval])) by (container)", "legendFormat": "__auto" } ], "title": "CPU Throttling", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 14 }, "id": 3, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}) by (container) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}) by (container) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}) by (container)", "format": "table", "instant": true } ], "title": "CPU Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "container", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Value #A": 6, "Value #B": 7, "Value #C": 8, "Value #D": 9, "Value #E": 10, "container": 5 }, "renameByName": { "Value #A": "CPU Usage", "Value #B": "CPU Requests", "Value #C": "CPU Requests %", "Value #D": "CPU Limits", "Value #E": "CPU Limits %", "container": "Container" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byFrameRefID", "options": "B" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash" } }, { "id": "custom.lineWidth", "value": 2 }, { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byFrameRefID", "options": "C" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash" } }, { "id": "custom.lineWidth", "value": 2 }, { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 21 }, "id": 4, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\", image!=\"\"}) by (container)", "legendFormat": "__auto" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"}\n)\n", "legendFormat": "requests" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"}\n)\n", "legendFormat": "limits" } ], "title": "Memory Usage (WSS)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 28 }, "id": 5, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\", image!=\"\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", image!=\"\"}) by (container) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\", image!=\"\"}) by (container) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_rss{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_cache{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(container_memory_swap{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", "format": "table", "instant": true } ], "title": "Memory Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "container", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true, "Time 7": true, "Time 8": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Time 7": 6, "Time 8": 7, "Value #A": 9, "Value #B": 10, "Value #C": 11, "Value #D": 12, "Value #E": 13, "Value #F": 14, "Value #G": 15, "Value #H": 16, "container": 8 }, "renameByName": { "Value #A": "Memory Usage", "Value #B": "Memory Requests", "Value #C": "Memory Requests %", "Value #D": "Memory Limits", "Value #E": "Memory Limits %", "Value #F": "Memory Usage (RSS)", "Value #G": "Memory Usage (Cache)", "Value #H": "Memory Usage (Swap)", "container": "Container" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 35 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(irate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Receive Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 35 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Transmit Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 42 }, "id": 8, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Rate of Received Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 42 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 49 }, "id": 10, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Rate of Received Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 49 }, "id": 11, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "iops" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 56 }, "id": 12, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "ceil(sum by(pod) (rate(container_fs_reads_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])))", "legendFormat": "Reads" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "ceil(sum by(pod) (rate(container_fs_writes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\",namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])))", "legendFormat": "Writes" } ], "title": "IOPS (Pod)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 56 }, "id": 13, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))", "legendFormat": "Reads" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(pod) (rate(container_fs_writes_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))", "legendFormat": "Writes" } ], "title": "ThroughPut (Pod)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "iops" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 63 }, "id": 14, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "ceil(sum by(container) (rate(container_fs_reads_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval])))", "legendFormat": "__auto" } ], "title": "IOPS (Containers)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 63 }, "id": 15, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(container) (rate(container_fs_reads_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", "legendFormat": "__auto" } ], "title": "ThroughPut (Containers)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/IOPS/" }, "properties": [ { "id": "unit", "value": "iops" } ] }, { "matcher": { "id": "byRegexp", "options": "/Throughput/" }, "properties": [ { "id": "unit", "value": "Bps" } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 70 }, "id": 16, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(container) (rate(container_fs_reads_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(container) (rate(container_fs_writes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\",device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(container) (rate(container_fs_reads_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(container) (rate(container_fs_reads_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(container) (rate(container_fs_writes_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by(container) (rate(container_fs_reads_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\", container!=\"\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", "format": "table", "instant": true } ], "title": "Current Storage IO", "transformations": [ { "id": "joinByField", "options": { "byField": "container", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Value #A": 7, "Value #B": 8, "Value #C": 9, "Value #D": 10, "Value #E": 11, "Value #F": 12, "container": 6 }, "renameByName": { "Value #A": "IOPS(Reads)", "Value #B": "IOPS(Writes)", "Value #C": "IOPS(Reads + Writes)", "Value #D": "Throughput(Read)", "Value #E": "Throughput(Write)", "Value #F": "Throughput(Read + Write)", "container": "Container" } } } ], "type": "table" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kube-state-metrics\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "namespace", "name": "namespace", "query": "label_values(kube_namespace_status_phase{job=\"kube-state-metrics\", cluster=\"$cluster\"}, namespace)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "pod", "name": "pod", "query": "label_values(kube_pod_info{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\"}, pod)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Compute Resources / Pod", "uid": "6581e46e4e5c7ba40a07646395ef7b23" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-k8s-resources-pod namespace: monitoring - apiVersion: v1 data: k8s-resources-windows-cluster.json: |- { "editable": false, "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "none" } }, "gridPos": { "h": 3, "w": 4, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "1 - avg(rate(windows_cpu_time_total{cluster=\"$cluster\", job=\"kubernetes-windows-exporter\", mode=\"idle\"}[$__rate_interval]))", "instant": true } ], "title": "CPU Utilisation", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 4, "y": 0 }, "id": 2, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_cpu_cores_request{cluster=\"$cluster\"}) / sum(node:windows_node_num_cpu:sum{cluster=\"$cluster\"})", "instant": true } ], "title": "CPU Requests Commitment", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 8, "y": 0 }, "id": 3, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_cpu_cores_limit{cluster=\"$cluster\"}) / sum(node:windows_node_num_cpu:sum{cluster=\"$cluster\"})", "instant": true } ], "title": "CPU Limits Commitment", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 12, "y": 0 }, "id": 4, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "1 - sum(:windows_node_memory_MemFreeCached_bytes:sum{cluster=\"$cluster\"}) / sum(:windows_node_memory_MemTotal_bytes:sum{cluster=\"$cluster\"})", "instant": true } ], "title": "Memory Utilisation", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 16, "y": 0 }, "id": 5, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_memory_request{cluster=\"$cluster\"}) / sum(:windows_node_memory_MemTotal_bytes:sum{cluster=\"$cluster\"})", "instant": true } ], "title": "Memory Requests Commitment", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "percentunit" } }, "gridPos": { "h": 3, "w": 4, "x": 20, "y": 0 }, "id": 6, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_memory_limit{cluster=\"$cluster\"}) / sum(:windows_node_memory_MemTotal_bytes:sum{cluster=\"$cluster\"})", "instant": true } ], "title": "Memory Limits Commitment", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true } } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 7 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_pod_container:windows_container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\"}) by (namespace)", "legendFormat": "__auto" } ], "title": "CPU Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Namespace" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/490b402361724ab1d4c45666c1fa9b6f/k8s-resources-windows-namespace?${datasource:queryparam}&var-cluster=$cluster&var-namespace=${__data.fields.Namespace}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 14 }, "id": 8, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_pod_container:windows_container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_cpu_cores_request{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_pod_container:windows_container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\"}) by (namespace) / sum(kube_pod_windows_container_resource_cpu_cores_request{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_cpu_cores_limit{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_pod_container:windows_container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\"}) by (namespace) / sum(kube_pod_windows_container_resource_cpu_cores_limit{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true } ], "title": "CPU Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "namespace", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Value #A": 6, "Value #B": 7, "Value #C": 8, "Value #D": 9, "Value #E": 10, "namespace": 5 }, "renameByName": { "Value #A": "CPU Usage", "Value #B": "CPU Requests", "Value #C": "CPU Requests %", "Value #D": "CPU Limits", "Value #E": "CPU Limits %", "namespace": "Namespace" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "decbytes" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 21 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(windows_container_private_working_set_usage{cluster=\"$cluster\"}) by (namespace)", "legendFormat": "__auto" } ], "title": "Memory Usage (Private Working Set)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Memory Usage" }, "properties": [ { "id": "unit", "value": "decbytes" } ] }, { "matcher": { "id": "byName", "options": "Memory Requests" }, "properties": [ { "id": "unit", "value": "decbytes" } ] }, { "matcher": { "id": "byName", "options": "Memory Limits" }, "properties": [ { "id": "unit", "value": "decbytes" } ] }, { "matcher": { "id": "byName", "options": "Namespace" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/490b402361724ab1d4c45666c1fa9b6f/k8s-resources-windows-namespace?${datasource:queryparam}&var-cluster=$cluster&var-namespace=${__data.fields.Namespace}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 28 }, "id": 10, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(windows_container_private_working_set_usage{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_memory_request{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(windows_container_private_working_set_usage{cluster=\"$cluster\"}) by (namespace) / sum(kube_pod_windows_container_resource_memory_request{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_memory_limit{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(windows_container_private_working_set_usage{cluster=\"$cluster\"}) by (namespace) / sum(kube_pod_windows_container_resource_memory_limit{cluster=\"$cluster\"}) by (namespace)", "format": "table", "instant": true } ], "title": "Memory Requests by Namespace", "transformations": [ { "id": "joinByField", "options": { "byField": "namespace", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Value #A": 6, "Value #B": 7, "Value #C": 8, "Value #D": 9, "Value #E": 10, "namespace": 5 }, "renameByName": { "Value #A": "Memory Usage", "Value #B": "Memory Requests", "Value #C": "Memory Requests %", "Value #D": "Memory Limits", "Value #E": "Memory Limits %", "namespace": "Namespace" } } } ], "type": "table" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kubernetes-windows-exporter\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "utc", "title": "Kubernetes / Compute Resources / Cluster(Windows)", "uid": "4d08557fd9391b100730f2494bccac68" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-k8s-resources-windows-cluster namespace: monitoring - apiVersion: v1 data: k8s-resources-windows-namespace.json: |- { "editable": false, "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true } } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_pod_container:windows_container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "legendFormat": "__auto" } ], "title": "CPU Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Pod" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/40597a704a610e936dc6ed374a7ce023/k8s-resources-windows-pod?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-pod=${__data.fields.Pod}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 7 }, "id": 2, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_pod_container:windows_container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_cpu_cores_request{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_pod_container:windows_container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod) / sum(kube_pod_windows_container_resource_cpu_cores_request{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_cpu_cores_limit{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_pod_container:windows_container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod) / sum(kube_pod_windows_container_resource_cpu_cores_limit{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true } ], "title": "CPU Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "pod", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Value #A": 6, "Value #B": 7, "Value #C": 8, "Value #D": 9, "Value #E": 10, "pod": 5 }, "renameByName": { "Value #A": "CPU Usage", "Value #B": "CPU Requests", "Value #C": "CPU Requests %", "Value #D": "CPU Limits", "Value #E": "CPU Limits %", "pod": "Pod" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "decbytes" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 14 }, "id": 3, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(windows_container_private_working_set_usage{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "legendFormat": "__auto" } ], "title": "Memory Usage (Private Working Set)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Pod" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/40597a704a610e936dc6ed374a7ce023/k8s-resources-windows-pod?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-pod=${__data.fields.Pod}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 21 }, "id": 4, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(windows_container_private_working_set_usage{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_memory_request{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(windows_container_private_working_set_usage{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod) / sum(kube_pod_windows_container_resource_memory_request{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_memory_limit{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(windows_container_private_working_set_usage{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod) / sum(kube_pod_windows_container_resource_memory_limit{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", "format": "table", "instant": true } ], "title": "Memory Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "pod", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Value #A": 6, "Value #B": 7, "Value #C": 8, "Value #D": 9, "Value #E": 10, "pod": 5 }, "renameByName": { "Value #A": "Memory Usage", "Value #B": "Memory Requests", "Value #C": "Memory Requests %", "Value #D": "Memory Limits", "Value #E": "Memory Limits %", "pod": "Pod" } } } ], "type": "table" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kubernetes-windows-exporter\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "namespace", "name": "namespace", "query": "label_values(windows_pod_container_available{cluster=\"$cluster\"}, namespace)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "utc", "title": "Kubernetes / Compute Resources / Namespace(Windows)", "uid": "490b402361724ab1d4c45666c1fa9b6f" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-k8s-resources-windows-namespace namespace: monitoring - apiVersion: v1 data: k8s-resources-windows-pod.json: |- { "editable": false, "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true } } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_pod_container:windows_container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "legendFormat": "__auto" } ], "title": "CPU Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Namespace" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/490b402361724ab1d4c45666c1fa9b6f/k8s-resources-windows-namespace?${datasource:queryparam}&var-cluster=$cluster&var-namespace=${__data.fields.Namespace}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 7 }, "id": 2, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_pod_container:windows_container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_cpu_cores_request{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_pod_container:windows_container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container) / sum(kube_pod_windows_container_resource_cpu_cores_request{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_cpu_cores_limit{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(namespace_pod_container:windows_container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container) / sum(kube_pod_windows_container_resource_cpu_cores_limit{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true } ], "title": "CPU Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "container", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Value #A": 6, "Value #B": 7, "Value #C": 8, "Value #D": 9, "Value #E": 10, "container": 5 }, "renameByName": { "Value #A": "CPU Usage", "Value #B": "CPU Requests", "Value #C": "CPU Requests %", "Value #D": "CPU Limits", "Value #E": "CPU Limits %", "container": "Container" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "decbytes" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 14 }, "id": 3, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(windows_container_private_working_set_usage{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "legendFormat": "__auto" } ], "title": "Memory Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 21 }, "id": 4, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(windows_container_private_working_set_usage{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_memory_request{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(windows_container_private_working_set_usage{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container) / sum(kube_pod_windows_container_resource_memory_request{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kube_pod_windows_container_resource_memory_limit{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(windows_container_private_working_set_usage{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container) / sum(kube_pod_windows_container_resource_memory_limit{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", "format": "table", "instant": true } ], "title": "Memory Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "container", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Value #A": 6, "Value #B": 7, "Value #C": 8, "Value #D": 9, "Value #E": 10, "container": 5 }, "renameByName": { "Value #A": "Memory Usage", "Value #B": "Memory Requests", "Value #C": "Memory Requests %", "Value #D": "Memory Limits", "Value #E": "Memory Limits %", "container": "Container" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "bytes" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 28 }, "id": 5, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum by (container) (rate(windows_container_network_received_bytes_total{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval])))", "legendFormat": "Received : {{ container }}" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum by (container) (rate(windows_container_network_transmitted_bytes_total{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval])))", "legendFormat": "Transmitted : {{ container }}" } ], "title": "Network I/O", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kubernetes-windows-exporter\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "namespace", "name": "namespace", "query": "label_values(windows_pod_container_available{cluster=\"$cluster\"}, namespace)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "pod", "name": "pod", "query": "label_values(windows_pod_container_available{cluster=\"$cluster\",namespace=\"$namespace\"}, pod)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "utc", "title": "Kubernetes / Compute Resources / Pod(Windows)", "uid": "40597a704a610e936dc6ed374a7ce023" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-k8s-resources-windows-pod namespace: monitoring - apiVersion: v1 data: k8s-resources-workload.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true } } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n", "legendFormat": "__auto" } ], "title": "CPU Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Pod" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-pod=${__data.fields.Pod}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 7 }, "id": 2, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n", "format": "table", "instant": true } ], "title": "CPU Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "pod", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Value #A": 6, "Value #B": 7, "Value #C": 8, "Value #D": 9, "Value #E": 10, "pod": 5 }, "renameByName": { "Value #A": "CPU Usage", "Value #B": "CPU Requests", "Value #C": "CPU Requests %", "Value #D": "CPU Limits", "Value #E": "CPU Limits %", "pod": "Pod" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "bytes" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 14 }, "id": 3, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n", "legendFormat": "__auto" } ], "title": "Memory Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Pod" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-pod=${__data.fields.Pod}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 21 }, "id": 4, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=~\"$type\"}\n) by (pod)\n", "format": "table", "instant": true } ], "title": "Memory Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "pod", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Value #A": 9, "Value #B": 10, "Value #C": 11, "Value #D": 12, "Value #E": 13, "pod": 8 }, "renameByName": { "Value #A": "Memory Usage", "Value #B": "Memory Requests", "Value #C": "Memory Requests %", "Value #D": "Memory Limits", "Value #E": "Memory Limits %", "pod": "Pod" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/Bandwidth/" }, "properties": [ { "id": "unit", "value": "Bps" } ] }, { "matcher": { "id": "byRegexp", "options": "/Packets/" }, "properties": [ { "id": "unit", "value": "pps" } ] }, { "matcher": { "id": "byName", "options": "Pod" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to pods", "url": "/d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-pod=${__data.fields.Pod}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 28 }, "id": 5, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_receive_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_transmit_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_receive_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_transmit_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "format": "table", "instant": true } ], "title": "Current Network Usage", "transformations": [ { "id": "joinByField", "options": { "byField": "pod", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Value #A": 7, "Value #B": 8, "Value #C": 9, "Value #D": 10, "Value #E": 11, "Value #F": 12, "pod": 6 }, "renameByName": { "Value #A": "Current Receive Bandwidth", "Value #B": "Current Transmit Bandwidth", "Value #C": "Rate of Received Packets", "Value #D": "Rate of Transmitted Packets", "Value #E": "Rate of Received Packets Dropped", "Value #F": "Rate of Transmitted Packets Dropped", "pod": "Pod" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 35 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Receive Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 35 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Transmit Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 42 }, "id": 8, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(avg(rate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Average Container Bandwidth by Pod: Received", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 42 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(avg(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Average Container Bandwidth by Pod: Transmitted", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 49 }, "id": 10, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_receive_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Rate of Received Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 49 }, "id": 11, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_transmit_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 56 }, "id": 12, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_receive_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Rate of Received Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 56 }, "id": 13, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_transmit_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets Dropped", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kube-state-metrics\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "namespace", "name": "namespace", "query": "label_values(kube_namespace_status_phase{job=\"kube-state-metrics\", cluster=\"$cluster\"}, namespace)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "label": "workload_type", "name": "type", "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\"}, workload_type)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "workload", "name": "workload", "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}, workload)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Compute Resources / Workload", "uid": "a164a7f0339f99e89cea5cb47e9be617" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-k8s-resources-workload namespace: monitoring - apiVersion: v1 data: k8s-resources-workloads-namespace.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true } }, "overrides": [ { "matcher": { "id": "byFrameRefID", "options": "B" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash" } }, { "id": "custom.lineWidth", "value": 2 }, { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byFrameRefID", "options": "C" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash" } }, { "id": "custom.lineWidth", "value": 2 }, { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n", "legendFormat": "{{workload}} - {{workload_type}}" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "scalar(max(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=~\"requests.cpu|cpu\"}))", "legendFormat": "quota - requests" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "scalar(max(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=~\"limits.cpu\"}))", "legendFormat": "quota - limits" } ], "title": "CPU Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Workload" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to workloads", "url": "/d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-type=${__data.fields.Type}&var-workload=${__data.fields.Workload}" } ] } ] }, { "matcher": { "id": "byName", "options": "Running Pods" }, "properties": [ { "id": "unit", "value": "none" } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 7 }, "id": 2, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "count(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}) by (workload, workload_type)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n", "format": "table", "instant": true } ], "title": "CPU Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "workload", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true, "workload_type 2": true, "workload_type 3": true, "workload_type 4": true, "workload_type 5": true, "workload_type 6": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Value #A": 8, "Value #B": 9, "Value #C": 10, "Value #D": 11, "Value #E": 12, "Value #F": 13, "workload": 6, "workload_type 1": 7, "workload_type 2": 14, "workload_type 3": 15, "workload_type 4": 16, "workload_type 5": 17, "workload_type 6": 18 }, "renameByName": { "Value #A": "Running Pods", "Value #B": "CPU Usage", "Value #C": "CPU Requests", "Value #D": "CPU Requests %", "Value #E": "CPU Limits", "Value #F": "CPU Limits %", "workload": "Workload", "workload_type 1": "Type" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byFrameRefID", "options": "B" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash" } }, { "id": "custom.lineWidth", "value": 2 }, { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byFrameRefID", "options": "C" }, "properties": [ { "id": "custom.lineStyle", "value": { "fill": "dash" } }, { "id": "custom.lineWidth", "value": 2 }, { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 14 }, "id": 3, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n", "legendFormat": "{{workload}} - {{workload_type}}" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "scalar(max(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=~\"requests.memory|memory\"}))", "legendFormat": "quota - requests" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "scalar(max(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=~\"limits.memory\"}))", "legendFormat": "quota - limits" } ], "title": "Memory Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/%/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] }, { "matcher": { "id": "byName", "options": "Workload" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to workloads", "url": "/d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-type=${__data.fields.Type}&var-workload=${__data.fields.Workload}" } ] } ] }, { "matcher": { "id": "byName", "options": "Running Pods" }, "properties": [ { "id": "unit", "value": "none" } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 21 }, "id": 4, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "count(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}) by (workload, workload_type)", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(\n container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}\n) by (workload, workload_type)\n", "format": "table", "instant": true } ], "title": "Memory Quota", "transformations": [ { "id": "joinByField", "options": { "byField": "workload", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true, "workload_type 2": true, "workload_type 3": true, "workload_type 4": true, "workload_type 5": true, "workload_type 6": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Value #A": 8, "Value #B": 9, "Value #C": 10, "Value #D": 11, "Value #E": 12, "Value #F": 13, "workload": 6, "workload_type 1": 7, "workload_type 2": 14, "workload_type 3": 15, "workload_type 4": 16, "workload_type 5": 17, "workload_type 6": 18 }, "renameByName": { "Value #A": "Running Pods", "Value #B": "Memory Usage", "Value #C": "Memory Requests", "Value #D": "Memory Requests %", "Value #E": "Memory Limits", "Value #F": "Memory Limits %", "workload": "Workload", "workload_type 1": "Type" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/Bandwidth/" }, "properties": [ { "id": "unit", "value": "Bps" } ] }, { "matcher": { "id": "byRegexp", "options": "/Packets/" }, "properties": [ { "id": "unit", "value": "pps" } ] }, { "matcher": { "id": "byName", "options": "Workload" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down to workloads", "url": "/d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?${datasource:queryparam}&var-cluster=$cluster&var-namespace=$namespace&var-type=${__data.fields.Type}&var-workload=${__data.fields.Workload}" } ] } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 28 }, "id": 5, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}) by (workload))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}) by (workload))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_receive_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}) by (workload))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_transmit_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}) by (workload))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_receive_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}) by (workload))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_transmit_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=~\"$type\"}) by (workload))\n", "format": "table", "instant": true } ], "title": "Current Network Usage", "transformations": [ { "id": "joinByField", "options": { "byField": "workload", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Value #A": 7, "Value #B": 8, "Value #C": 9, "Value #D": 10, "Value #E": 11, "Value #F": 12, "workload": 6 }, "renameByName": { "Value #A": "Current Receive Bandwidth", "Value #B": "Current Transmit Bandwidth", "Value #C": "Rate of Received Packets", "Value #D": "Rate of Transmitted Packets", "Value #E": "Rate of Received Packets Dropped", "Value #F": "Rate of Transmitted Packets Dropped", "workload": "Workload" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 35 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Receive Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 35 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Transmit Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 42 }, "id": 8, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(avg(rate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Average Container Bandwidth by Workload: Received", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 42 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(avg(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Average Container Bandwidth by Workload: Transmitted", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 49 }, "id": 10, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_receive_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Rate of Received Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 49 }, "id": 11, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_transmit_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 56 }, "id": 12, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_receive_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Rate of Received Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 56 }, "id": 13, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(sum(rate(container_network_transmit_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets Dropped", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kube-state-metrics\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "namespace", "name": "namespace", "query": "label_values(kube_namespace_status_phase{job=\"kube-state-metrics\", cluster=\"$cluster\"}, namespace)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "label": "workload_type", "name": "type", "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\".+\"}, workload_type)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Compute Resources / Namespace (Workloads)", "uid": "a87fb0d919ec0ea5f6543124e16c42a5" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-k8s-resources-workloads-namespace namespace: monitoring - apiVersion: v1 data: k8s-windows-cluster-rsrc-use.json: |- { "editable": false, "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "node:windows_node_cpu_utilisation:avg1m{cluster=\"$cluster\"} * node:windows_node_num_cpu:sum{cluster=\"$cluster\"} / scalar(sum(node:windows_node_num_cpu:sum{cluster=\"$cluster\"}))", "legendFormat": "{{instance}}" } ], "title": "CPU Utilisation", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 7 }, "id": 2, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "node:windows_node_memory_utilisation:ratio{cluster=\"$cluster\"}", "legendFormat": "{{instance}}" } ], "title": "Memory Utilisation", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "short" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 7 }, "id": 3, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "node:windows_node_memory_swap_io_pages:irate{cluster=\"$cluster\"}", "legendFormat": "{{instance}}" } ], "title": "Memory Saturation (Swap I/O Pages)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 14 }, "id": 4, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "node:windows_node_disk_utilisation:avg_irate{cluster=\"$cluster\"} / scalar(node:windows_node:sum{cluster=\"$cluster\"})", "legendFormat": "{{instance}}" } ], "title": "Disk IO Utilisation", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 21 }, "id": 5, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "node:windows_node_net_utilisation:sum_irate{cluster=\"$cluster\"}", "legendFormat": "{{instance}}" } ], "title": "Net Utilisation (Transmitted)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 21 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "node:windows_node_net_saturation:sum_irate{cluster=\"$cluster\"}", "legendFormat": "{{instance}}" } ], "title": "Net Utilisation (Dropped)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 28 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (instance)(node:windows_node_filesystem_usage:{cluster=\"$cluster\"})", "legendFormat": "{{instance}}" } ], "title": "Disk Capacity", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kubernetes-windows-exporter\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "utc", "title": "Kubernetes / USE Method / Cluster(Windows)", "uid": "53a43377ec9aaf2ff64dfc7a1f539334" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-k8s-windows-cluster-rsrc-use namespace: monitoring - apiVersion: v1 data: k8s-windows-node-rsrc-use.json: |- { "editable": false, "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "node:windows_node_cpu_utilisation:avg1m{cluster=\"$cluster\", instance=\"$instance\"}", "legendFormat": "Utilisation" } ], "title": "CPU Utilisation", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 0 }, "id": 2, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (core) (irate(windows_cpu_time_total{cluster=\"$cluster\", job=\"kubernetes-windows-exporter\", mode!=\"idle\", instance=\"$instance\"}[$__rate_interval]))", "legendFormat": "{{core}}" } ], "title": "CPU Usage Per Core", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 7 }, "id": 3, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "node:windows_node_memory_utilisation:{cluster=\"$cluster\", instance=\"$instance\"}", "legendFormat": "Memory" } ], "title": "Memory Utilisation %", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "bytes" } }, "gridPos": { "h": 7, "w": 8, "x": 8, "y": 7 }, "id": 4, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "max(\n windows_os_visible_memory_bytes{cluster=\"$cluster\", job=\"kubernetes-windows-exporter\", instance=\"$instance\"}\n - windows_memory_available_bytes{cluster=\"$cluster\", job=\"kubernetes-windows-exporter\", instance=\"$instance\"}\n)\n", "legendFormat": "memory used" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "max(node:windows_node_memory_totalCached_bytes:sum{cluster=\"$cluster\", instance=\"$instance\"})", "legendFormat": "memory cached" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "max(windows_memory_available_bytes{cluster=\"$cluster\", job=\"kubernetes-windows-exporter\", instance=\"$instance\"})", "legendFormat": "memory free" } ], "title": "Memory Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 16, "y": 7 }, "id": 5, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "node:windows_node_memory_swap_io_pages:irate{cluster=\"$cluster\", instance=\"$instance\"}", "legendFormat": "Swap IO" } ], "title": "Memory Saturation (Swap I/O) Pages", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 14 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "node:windows_node_disk_utilisation:avg_irate{cluster=\"$cluster\", instance=\"$instance\"}", "legendFormat": "Utilisation" } ], "title": "Disk IO Utilisation", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/io time/" }, "properties": [ { "id": "unit", "value": "ms" } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 14 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "max(rate(windows_logical_disk_read_bytes_total{cluster=\"$cluster\", job=\"kubernetes-windows-exporter\", instance=\"$instance\"}[$__rate_interval]))", "legendFormat": "read" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "max(rate(windows_logical_disk_write_bytes_total{cluster=\"$cluster\", job=\"kubernetes-windows-exporter\", instance=\"$instance\"}[$__rate_interval]))", "legendFormat": "written" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "max(rate(windows_logical_disk_read_seconds_total{cluster=\"$cluster\", job=\"kubernetes-windows-exporter\", instance=\"$instance\"}[$__rate_interval]) + rate(windows_logical_disk_write_seconds_total{cluster=\"$cluster\", job=\"kubernetes-windows-exporter\", instance=\"$instance\"}[$__rate_interval]))", "legendFormat": "io time" } ], "title": "Disk IO", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 21 }, "id": 8, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "node:windows_node_filesystem_usage:{cluster=\"$cluster\", instance=\"$instance\"}", "legendFormat": "{{volume}}" } ], "title": "Disk Utilisation", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 28 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "node:windows_node_net_utilisation:sum_irate{cluster=\"$cluster\", instance=\"$instance\"}", "legendFormat": "Utilisation" } ], "title": "Net Utilisation (Transmitted)", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 28 }, "id": 10, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "node:windows_node_net_saturation:sum_irate{cluster=\"$cluster\", instance=\"$instance\"}", "legendFormat": "Saturation" } ], "title": "Net Saturation (Dropped)", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kubernetes-windows-exporter\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "instance", "name": "instance", "query": "label_values(windows_system_boot_time_timestamp_seconds{cluster=\"$cluster\"}, instance)", "refresh": 2, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "utc", "title": "Kubernetes / USE Method / Node(Windows)", "uid": "96e7484b0bb53b74fbc2bcb7723cd40b" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-k8s-windows-node-rsrc-use namespace: monitoring - apiVersion: v1 data: kubelet.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "none" } }, "gridPos": { "h": 7, "w": 4, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kubelet_node_name{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\"})", "instant": true } ], "title": "Running Kubelets", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "none" } }, "gridPos": { "h": 7, "w": 4, "x": 4, "y": 0 }, "id": 2, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kubelet_running_pods{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"})", "instant": true } ], "title": "Running Pods", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "none" } }, "gridPos": { "h": 7, "w": 4, "x": 8, "y": 0 }, "id": 3, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(kubelet_running_containers{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"})", "instant": true } ], "title": "Running Containers", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "none" } }, "gridPos": { "h": 7, "w": 4, "x": 12, "y": 0 }, "id": 4, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(volume_manager_total_volumes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\", state=\"actual_state_of_world\"})", "instant": true } ], "title": "Actual Volume Count", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "none" } }, "gridPos": { "h": 7, "w": 4, "x": 16, "y": 0 }, "id": 5, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(volume_manager_total_volumes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\",state=\"desired_state_of_world\"})", "instant": true } ], "title": "Desired Volume Count", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "none" } }, "gridPos": { "h": 7, "w": 4, "x": 20, "y": 0 }, "id": 6, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(kubelet_node_config_error{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"}[$__rate_interval]))", "instant": true } ], "title": "Config Error Count", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 7 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(kubelet_runtime_operations_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[$__rate_interval])) by (operation_type, instance)", "legendFormat": "{{instance}} {{operation_type}}" } ], "title": "Operation Rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 7 }, "id": 8, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(kubelet_runtime_operations_errors_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[$__rate_interval])) by (instance, operation_type)", "legendFormat": "{{instance}} {{operation_type}}" } ], "title": "Operation Error Rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 14 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(kubelet_runtime_operations_duration_seconds_bucket{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[$__rate_interval])) by (instance, operation_type, le))", "legendFormat": "{{instance}} {{operation_type}}" } ], "title": "Operation Duration 99th quantile", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 21 }, "id": 10, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(kubelet_pod_start_duration_seconds_count{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[$__rate_interval])) by (instance)", "legendFormat": "{{instance}} pod" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(kubelet_pod_worker_duration_seconds_count{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[$__rate_interval])) by (instance)", "legendFormat": "{{instance}} worker" } ], "title": "Pod Start Rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 21 }, "id": 11, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(kubelet_pod_start_duration_seconds_bucket{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[$__rate_interval])) by (instance, le))", "legendFormat": "{{instance}} pod" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(kubelet_pod_worker_duration_seconds_bucket{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[$__rate_interval])) by (instance, le))", "legendFormat": "{{instance}} worker" } ], "title": "Pod Start Duration", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 28 }, "id": 12, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(storage_operation_duration_seconds_count{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[$__rate_interval])) by (instance, operation_name, volume_plugin)", "legendFormat": "{{instance}} {{operation_name}} {{volume_plugin}}" } ], "title": "Storage Operation Rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 28 }, "id": 13, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(storage_operation_errors_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[$__rate_interval])) by (instance, operation_name, volume_plugin)", "legendFormat": "{{instance}} {{operation_name}} {{volume_plugin}}" } ], "title": "Storage Operation Error Rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 35 }, "id": 14, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(storage_operation_duration_seconds_bucket{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"}[$__rate_interval])) by (instance, operation_name, volume_plugin, le))", "legendFormat": "{{instance}} {{operation_name}} {{volume_plugin}}" } ], "title": "Storage Operation Duration 99th quantile", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 42 }, "id": 15, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(kubelet_cgroup_manager_duration_seconds_count{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"}[$__rate_interval])) by (instance, operation_type)", "legendFormat": "{{operation_type}}" } ], "title": "Cgroup manager operation rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 42 }, "id": 16, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(kubelet_cgroup_manager_duration_seconds_bucket{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"}[$__rate_interval])) by (instance, operation_type, le))", "legendFormat": "{{instance}} {{operation_type}}" } ], "title": "Cgroup manager 99th quantile", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 49 }, "id": 17, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(kubelet_pleg_relist_duration_seconds_count{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"}[$__rate_interval])) by (instance)", "legendFormat": "{{instance}}" } ], "title": "PLEG relist rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 49 }, "id": 18, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(kubelet_pleg_relist_interval_seconds_bucket{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[$__rate_interval])) by (instance, le))", "legendFormat": "{{instance}}" } ], "title": "PLEG relist interval", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 56 }, "id": 19, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(kubelet_pleg_relist_duration_seconds_bucket{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[$__rate_interval])) by (instance, le))", "legendFormat": "{{instance}}" } ], "title": "PLEG relist duration", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 63 }, "id": 20, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\",code=~\"2..\"}[$__rate_interval]))", "legendFormat": "2xx" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\",code=~\"3..\"}[$__rate_interval]))", "legendFormat": "3xx" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\",code=~\"4..\"}[$__rate_interval]))", "legendFormat": "4xx" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\",code=~\"5..\"}[$__rate_interval]))", "legendFormat": "5xx" } ], "title": "RPC rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 70 }, "id": 21, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"}[$__rate_interval])) by (instance, verb, le))", "legendFormat": "{{instance}} {{verb}}" } ], "title": "Request duration 99th quantile", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "bytes" } }, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 77 }, "id": 22, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "process_resident_memory_bytes{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}", "legendFormat": "{{instance}}" } ], "title": "Memory", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 8, "y": 77 }, "id": 23, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "rate(process_cpu_seconds_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[$__rate_interval])", "legendFormat": "{{instance}}" } ], "title": "CPU usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 16, "y": 77 }, "id": 24, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "go_goroutines{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}", "legendFormat": "{{instance}}" } ], "title": "Goroutines", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kubelet\", metrics_path=\"/metrics\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "label": "instance", "name": "instance", "query": "label_values(up{job=\"kubelet\", metrics_path=\"/metrics\",cluster=\"$cluster\"}, instance)", "refresh": 2, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Kubelet", "uid": "3138fa155d5915769fbded898ac09fd9" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-kubelet namespace: monitoring - apiVersion: v1 data: namespace-by-pod.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "displayName": "$namespace", "max": 10000000000, "min": 0, "thresholds": { "steps": [ { "color": "dark-green", "index": 0, "value": null }, { "color": "dark-yellow", "index": 1, "value": 5000000000 }, { "color": "dark-red", "index": 2, "value": 7000000000 } ] }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum (\n rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Current Rate of Bytes Received", "type": "gauge" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "displayName": "$namespace", "max": 10000000000, "min": 0, "thresholds": { "steps": [ { "color": "dark-green", "index": 0, "value": null }, { "color": "dark-yellow", "index": 1, "value": 5000000000 }, { "color": "dark-red", "index": 2, "value": 7000000000 } ] }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 0 }, "id": 2, "interval": "1m", "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum (\n rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Current Rate of Bytes Transmitted", "type": "gauge" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/Bandwidth/" }, "properties": [ { "id": "unit", "value": "Bps" } ] }, { "matcher": { "id": "byRegexp", "options": "/Packets/" }, "properties": [ { "id": "unit", "value": "pps" } ] }, { "matcher": { "id": "byName", "options": "Pod" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down", "url": "/d/7a18067ce943a40ae25454675c19ff5c/kubernetes-networking-pod?${datasource:queryparam}&var-cluster=${cluster}&var-namespace=${namespace}&var-pod=${__data.fields.Pod}" } ] } ] } ] }, "gridPos": { "h": 9, "w": 24, "x": 0, "y": 9 }, "id": 3, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (pod) (\n rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (pod) (\n rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (pod) (\n rate(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (pod) (\n rate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (pod) (\n rate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (pod) (\n rate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "format": "table", "instant": true } ], "title": "Current Network Usage", "transformations": [ { "id": "joinByField", "options": { "byField": "pod", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Value #A": 7, "Value #B": 8, "Value #C": 9, "Value #D": 10, "Value #E": 11, "Value #F": 12, "pod": 6 }, "renameByName": { "Value #A": "Current Receive Bandwidth", "Value #B": "Current Transmit Bandwidth", "Value #C": "Rate of Received Packets", "Value #D": "Rate of Transmitted Packets", "Value #E": "Rate of Received Packets Dropped", "Value #F": "Rate of Transmitted Packets Dropped", "pod": "Pod" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "binBps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 18 }, "id": 4, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (pod) (\n rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Receive Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "binBps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 18 }, "id": 5, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (pod) (\n rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Transmit Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 27 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (pod) (\n rate(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Rate of Received Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 27 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (pod) (\n rate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 36 }, "id": 8, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (pod) (\n rate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace!=\"\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Rate of Received Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 36 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum by (pod) (\n rate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n * on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n)\n", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets Dropped", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "allValue": ".+", "current": { "selected": false, "text": "kube-system", "value": "kube-system" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "label": "namespace", "name": "namespace", "query": "label_values(container_network_receive_packets_total{cluster=\"$cluster\"}, namespace)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Networking / Namespace (Pods)", "uid": "8b7a8b326d7a6f1f04244066368c67af" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-namespace-by-pod namespace: monitoring - apiVersion: v1 data: namespace-by-workload.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "color": { "fixedColor": "green", "mode": "fixed" }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "displayMode": "basic", "showUnfilled": false }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n* on (cluster,namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Current Rate of Bytes Received", "type": "bargauge" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "color": { "fixedColor": "green", "mode": "fixed" }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 0 }, "id": 2, "interval": "1m", "options": { "displayMode": "basic", "showUnfilled": false }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n* on (cluster,namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Current Rate of Bytes Transmitted", "type": "bargauge" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "overrides": [ { "matcher": { "id": "byRegexp", "options": "/Bytes/" }, "properties": [ { "id": "unit", "value": "binBps" } ] }, { "matcher": { "id": "byRegexp", "options": "/Packets/" }, "properties": [ { "id": "unit", "value": "pps" } ] }, { "matcher": { "id": "byName", "options": "Workload" }, "properties": [ { "id": "links", "value": [ { "title": "Drill down", "url": "/d/728bf77cc1166d2f3133bf25846876cc/kubernetes-networking-workload?${datasource:queryparam}&var-cluster=${cluster}&var-namespace=${namespace}&var-type=${__data.fields.Type}&var-workload=${__data.fields.Workload}" } ] } ] } ] }, "gridPos": { "h": 9, "w": 24, "x": 0, "y": 9 }, "id": 3, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod) kube_pod_info{cluster=\"$cluster\",namespace=\"$namespace\",host_network=\"false\"}\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload, workload_type))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod) kube_pod_info{cluster=\"$cluster\",namespace=\"$namespace\",host_network=\"false\"}\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload, workload_type))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(avg(rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod) kube_pod_info{cluster=\"$cluster\",namespace=\"$namespace\",host_network=\"false\"}\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload, workload_type))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(avg(rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod) kube_pod_info{cluster=\"$cluster\",namespace=\"$namespace\",host_network=\"false\"}\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload, workload_type))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_receive_packets_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod) kube_pod_info{cluster=\"$cluster\",namespace=\"$namespace\",host_network=\"false\"}\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload, workload_type))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod) kube_pod_info{cluster=\"$cluster\",namespace=\"$namespace\",host_network=\"false\"}\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload, workload_type))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod) kube_pod_info{cluster=\"$cluster\",namespace=\"$namespace\",host_network=\"false\"}\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload, workload_type))\n", "format": "table", "instant": true }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod) kube_pod_info{cluster=\"$cluster\",namespace=\"$namespace\",host_network=\"false\"}\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload, workload_type))\n", "format": "table", "instant": true } ], "title": "Current Status", "transformations": [ { "id": "joinByField", "options": { "byField": "workload", "mode": "outer" } }, { "id": "organize", "options": { "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "Time 5": true, "Time 6": true, "Time 7": true, "Time 8": true, "workload_type 2": true, "workload_type 3": true, "workload_type 4": true, "workload_type 5": true, "workload_type 6": true, "workload_type 7": true, "workload_type 8": true }, "indexByName": { "Time 1": 0, "Time 2": 1, "Time 3": 2, "Time 4": 3, "Time 5": 4, "Time 6": 5, "Time 7": 6, "Time 8": 7, "Value #A": 10, "Value #B": 11, "Value #C": 12, "Value #D": 13, "Value #E": 14, "Value #F": 15, "Value #G": 16, "Value #H": 17, "workload": 8, "workload_type 1": 9, "workload_type 2": 18, "workload_type 3": 19, "workload_type 4": 20, "workload_type 5": 21, "workload_type 6": 22, "workload_type 7": 23, "workload_type 8": 24 }, "renameByName": { "Value #A": "Rx Bytes", "Value #B": "Tx Bytes", "Value #C": "Rx Bytes (Avg)", "Value #D": "Tx Bytes (Avg)", "Value #E": "Rx Packets", "Value #F": "Tx Packets", "Value #G": "Rx Packets Dropped", "Value #H": "Tx Packets Dropped", "workload": "Workload", "workload_type 1": "Type" } } } ], "type": "table" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 18 }, "id": 4, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n* on (cluster,namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Receive Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 18 }, "id": 5, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n* on (cluster,namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Transmit Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 27 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(avg(rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n* on (cluster,namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Average Container Bandwidth by Workload: Received", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 27 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(avg(rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n* on (cluster,namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Average Container Bandwidth by Workload: Transmitted", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 36 }, "id": 8, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_receive_packets_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n* on (cluster,namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Rate of Received Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 36 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n* on (cluster,namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 45 }, "id": 10, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n* on (cluster,namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Rate of Received Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 45 }, "id": 11, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace=\"$namespace\"}[$__rate_interval])\n* on (cluster,namespace,pod) group_left ()\n topk by (cluster,namespace,pod) (\n 1,\n max by (cluster,namespace,pod) (kube_pod_info{host_network=\"false\"})\n )\n* on (cluster,namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=\"$namespace\", workload=~\".+\", workload_type=~\"$type\"}) by (workload))\n", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets Dropped", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "current": { "selected": false, "text": "kube-system", "value": "kube-system" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "namespace", "name": "namespace", "query": "label_values(container_network_receive_packets_total{cluster=\"$cluster\"}, namespace)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "label": "workload_type", "name": "type", "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=~\".+\"}, workload_type)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Networking / Namespace (Workload)", "uid": "bbb2a765a623ae38130206c7d94a160f" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-namespace-by-workload namespace: monitoring - apiVersion: v1 data: node-cluster-rsrc-use.json: |- { "graphTooltip": 1, "panels": [ { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 1, "panels": [ ], "title": "CPU", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 1 }, "id": 2, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "((\n instance:node_cpu_utilisation:rate5m{job=\"node-exporter\", cluster=\"$cluster\"}\n *\n instance:node_num_cpu:sum{job=\"node-exporter\", cluster=\"$cluster\"}\n) != 0 )\n/ scalar(sum(instance:node_num_cpu:sum{job=\"node-exporter\", cluster=\"$cluster\"}))\n", "legendFormat": "{{ instance }}" } ], "title": "CPU Utilisation", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 1 }, "id": 3, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "(\n instance:node_load1_per_cpu:ratio{job=\"node-exporter\", cluster=\"$cluster\"}\n / scalar(count(instance:node_load1_per_cpu:ratio{job=\"node-exporter\", cluster=\"$cluster\"}))\n) != 0\n", "legendFormat": "{{ instance }}" } ], "title": "CPU Saturation (Load1 per CPU)", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 8 }, "id": 4, "panels": [ ], "title": "Memory", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 9 }, "id": 5, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "(\n instance:node_memory_utilisation:ratio{job=\"node-exporter\", cluster=\"$cluster\"}\n / scalar(count(instance:node_memory_utilisation:ratio{job=\"node-exporter\", cluster=\"$cluster\"}))\n) != 0\n", "legendFormat": "{{ instance }}" } ], "title": "Memory Utilisation", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "rds" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 9 }, "id": 6, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance:node_vmstat_pgmajfault:rate5m{job=\"node-exporter\", cluster=\"$cluster\"}", "legendFormat": "{{ instance }}" } ], "title": "Memory Saturation (Major Page Faults)", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 16 }, "id": 7, "panels": [ ], "title": "Network", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "Bps" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/Transmit/" }, "properties": [ { "id": "custom.transform", "value": "negative-Y" } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 17 }, "id": 8, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance:node_network_receive_bytes_excluding_lo:rate5m{job=\"node-exporter\", cluster=\"$cluster\"} != 0", "legendFormat": "{{ instance }} Receive" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance:node_network_transmit_bytes_excluding_lo:rate5m{job=\"node-exporter\", cluster=\"$cluster\"} != 0", "legendFormat": "{{ instance }} Transmit" } ], "title": "Network Utilisation (Bytes Receive/Transmit)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "Bps" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/Transmit/" }, "properties": [ { "id": "custom.transform", "value": "negative-Y" } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 17 }, "id": 9, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance:node_network_receive_drop_excluding_lo:rate5m{job=\"node-exporter\", cluster=\"$cluster\"} != 0", "legendFormat": "{{ instance }} Receive" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance:node_network_transmit_drop_excluding_lo:rate5m{job=\"node-exporter\", cluster=\"$cluster\"} != 0", "legendFormat": "{{ instance }} Transmit" } ], "title": "Network Saturation (Drops Receive/Transmit)", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 24 }, "id": 10, "panels": [ ], "title": "Disk IO", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 25 }, "id": 11, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance_device:node_disk_io_time_seconds:rate5m{job=\"node-exporter\", cluster=\"$cluster\"}\n/ scalar(count(instance_device:node_disk_io_time_seconds:rate5m{job=\"node-exporter\", cluster=\"$cluster\"}))\n", "legendFormat": "{{ instance }} {{device}}" } ], "title": "Disk IO Utilisation", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 25 }, "id": 12, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance_device:node_disk_io_time_weighted_seconds:rate5m{job=\"node-exporter\", cluster=\"$cluster\"}\n/ scalar(count(instance_device:node_disk_io_time_weighted_seconds:rate5m{job=\"node-exporter\", cluster=\"$cluster\"}))\n", "legendFormat": "{{ instance }} {{device}}" } ], "title": "Disk IO Saturation", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 34 }, "id": 13, "panels": [ ], "title": "Disk Space", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 35 }, "id": 14, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum without (device) (\n max without (fstype, mountpoint) ((\n node_filesystem_size_bytes{job=\"node-exporter\", fstype!=\"\", mountpoint!=\"\", cluster=\"$cluster\"}\n -\n node_filesystem_avail_bytes{job=\"node-exporter\", fstype!=\"\", mountpoint!=\"\", cluster=\"$cluster\"}\n ) != 0)\n)\n/ scalar(sum(max without (fstype, mountpoint) (node_filesystem_size_bytes{job=\"node-exporter\", fstype!=\"\", mountpoint!=\"\", cluster=\"$cluster\"})))\n", "legendFormat": "{{ instance }}" } ], "title": "Disk Space Utilisation", "type": "timeseries" } ], "refresh": "30s", "schemaVersion": 39, "tags": [ "node-exporter-mixin" ], "templating": { "list": [ { "name": "datasource", "query": "prometheus", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 2, "includeAll": false, "name": "cluster", "query": "label_values(node_time_seconds, cluster)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "utc", "title": "Node Exporter / USE Method / Cluster", "uid": "3e97d1d02672cdd0861f4c97c64f89b2" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-node-cluster-rsrc-use namespace: monitoring - apiVersion: v1 data: node-rsrc-use.json: |- { "graphTooltip": 1, "panels": [ { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 1, "panels": [ ], "title": "CPU", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 1 }, "id": 2, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance:node_cpu_utilisation:rate5m{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} != 0", "legendFormat": "Utilisation" } ], "title": "CPU Utilisation", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 1 }, "id": 3, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance:node_load1_per_cpu:ratio{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} != 0", "legendFormat": "Saturation" } ], "title": "CPU Saturation (Load1 per CPU)", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 8 }, "id": 4, "panels": [ ], "title": "Memory", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 9 }, "id": 5, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance:node_memory_utilisation:ratio{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} != 0", "legendFormat": "Utilisation" } ], "title": "Memory Utilisation", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "rds" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 9 }, "id": 6, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance:node_vmstat_pgmajfault:rate5m{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} != 0", "legendFormat": "Major page Faults" } ], "title": "Memory Saturation (Major Page Faults)", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 16 }, "id": 7, "panels": [ ], "title": "Network", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "Bps" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/Transmit/" }, "properties": [ { "id": "custom.transform", "value": "negative-Y" } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 17 }, "id": 8, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance:node_network_receive_bytes_excluding_lo:rate5m{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} != 0", "legendFormat": "Receive" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance:node_network_transmit_bytes_excluding_lo:rate5m{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} != 0", "legendFormat": "Transmit" } ], "title": "Network Utilisation (Bytes Receive/Transmit)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "Bps" }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/Transmit/" }, "properties": [ { "id": "custom.transform", "value": "negative-Y" } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 17 }, "id": 9, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance:node_network_receive_drop_excluding_lo:rate5m{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} != 0", "legendFormat": "Receive" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance:node_network_transmit_drop_excluding_lo:rate5m{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} != 0", "legendFormat": "Transmit" } ], "title": "Network Saturation (Drops Receive/Transmit)", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 24 }, "id": 10, "panels": [ ], "title": "Disk IO", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 25 }, "id": 11, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance_device:node_disk_io_time_seconds:rate5m{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} != 0", "legendFormat": "{{device}}" } ], "title": "Disk IO Utilisation", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 25 }, "id": 12, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "instance_device:node_disk_io_time_weighted_seconds:rate5m{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} != 0", "legendFormat": "{{device}}" } ], "title": "Disk IO Saturation", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 34 }, "id": 13, "panels": [ ], "title": "Disk Space", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "showPoints": "never", "stacking": { "mode": "normal" } }, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 35 }, "id": 14, "options": { "legend": { "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sort_desc(1 -\n (\n max without (mountpoint, fstype) (node_filesystem_avail_bytes{job=\"node-exporter\", fstype!=\"\", instance=\"$instance\", cluster=\"$cluster\"})\n /\n max without (mountpoint, fstype) (node_filesystem_size_bytes{job=\"node-exporter\", fstype!=\"\", instance=\"$instance\", cluster=\"$cluster\"})\n ) != 0\n)\n", "legendFormat": "{{device}}" } ], "title": "Disk Space Utilisation", "type": "timeseries" } ], "refresh": "30s", "schemaVersion": 39, "tags": [ "node-exporter-mixin" ], "templating": { "list": [ { "name": "datasource", "query": "prometheus", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 2, "includeAll": false, "name": "cluster", "query": "label_values(node_time_seconds, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "name": "instance", "query": "label_values(node_exporter_build_info{job=\"node-exporter\", cluster=\"$cluster\"}, instance)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "utc", "title": "Node Exporter / USE Method / Node", "uid": "fac67cfbe174d3ef53eb473d73d9212f" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-node-rsrc-use namespace: monitoring - apiVersion: v1 data: nodes-aix.json: |- { "graphTooltip": 1, "panels": [ { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 1, "panels": [ ], "title": "CPU", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "stacking": { "mode": "normal" } }, "max": 1, "min": 0, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 1 }, "id": 2, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "(\n (1 - sum without (mode) (rate(node_cpu_seconds_total{job=\"node-exporter\", mode=~\"idle|iowait|steal\", instance=\"$instance\", cluster=\"$cluster\"}[$__rate_interval])))\n/ ignoring(cpu) group_left\n count without (cpu, mode) (node_cpu_seconds_total{job=\"node-exporter\", mode=\"idle\", instance=\"$instance\", cluster=\"$cluster\"})\n)\n", "intervalFactor": 5, "legendFormat": "{{cpu}}" } ], "title": "CPU Usage", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" }, "min": 0, "unit": "short" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 1 }, "id": 3, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_load1{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "1m load average" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_load5{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "5m load average" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_load15{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "15m load average" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "count(node_cpu_seconds_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", mode=\"idle\"})", "legendFormat": "logical cores" } ], "title": "Load Average", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 8 }, "id": 4, "title": "Memory", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "stacking": { "mode": "none" } }, "min": 0, "unit": "bytes" } }, "gridPos": { "h": 7, "w": 18, "x": 0, "y": 9 }, "id": 5, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_memory_total_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "Physical Memory" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "(\n node_memory_total_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} -\n node_memory_available_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}\n)\n", "legendFormat": "Memory Used" } ], "title": "Memory Usage", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "max": 100, "min": 0, "thresholds": { "steps": [ { "color": "rgba(50, 172, 45, 0.97)" }, { "color": "rgba(237, 129, 40, 0.89)", "value": 80 }, { "color": "rgba(245, 54, 54, 0.9)", "value": 90 } ] }, "unit": "percent" } }, "gridPos": { "h": 7, "w": 6, "x": 18, "y": 9 }, "id": 6, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "100 -\n(\n avg(node_memory_available_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}) /\n avg(node_memory_total_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"})\n * 100\n)\n" } ], "title": "Memory Usage", "type": "gauge" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 18 }, "id": 7, "panels": [ ], "title": "Disk", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" }, "min": 0 }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/ read| written/" }, "properties": [ { "id": "unit", "value": "Bps" } ] }, { "matcher": { "id": "byRegexp", "options": "/ io time/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 19 }, "id": 8, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_disk_read_bytes_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\"}[$__rate_interval])", "intervalFactor": 1, "legendFormat": "{{device}} read" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_disk_written_bytes_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\"}[$__rate_interval])", "intervalFactor": 1, "legendFormat": "{{device}} written" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_disk_io_time_seconds_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\"}[$__rate_interval])", "intervalFactor": 1, "legendFormat": "{{device}} io time" } ], "title": "Disk I/O", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "thresholds": { "steps": [ { "color": "green" }, { "color": "yellow", "value": 0.8 }, { "color": "red", "value": 0.9 } ] }, "unit": "decbytes" }, "overrides": [ { "matcher": { "id": "byName", "options": "Mounted on" }, "properties": [ { "id": "custom.width", "value": 260 } ] }, { "matcher": { "id": "byName", "options": "Size" }, "properties": [ { "id": "custom.width", "value": 93 } ] }, { "matcher": { "id": "byName", "options": "Used" }, "properties": [ { "id": "custom.width", "value": 72 } ] }, { "matcher": { "id": "byName", "options": "Available" }, "properties": [ { "id": "custom.width", "value": 88 } ] }, { "matcher": { "id": "byName", "options": "Used, %" }, "properties": [ { "id": "unit", "value": "percentunit" }, { "id": "custom.cellOptions", "value": { "type": "gauge" } }, { "id": "max", "value": 1 }, { "id": "min", "value": 0 } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 19 }, "id": 9, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "max by (mountpoint) (node_filesystem_size_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", fstype!=\"\", mountpoint!=\"\"})\n", "format": "table", "instant": true, "legendFormat": "" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "max by (mountpoint) (node_filesystem_avail_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", fstype!=\"\", mountpoint!=\"\"})\n", "format": "table", "instant": true, "legendFormat": "" } ], "title": "Disk Space Usage", "transformations": [ { "id": "groupBy", "options": { "fields": { "Value #A": { "aggregations": [ "lastNotNull" ], "operation": "aggregate" }, "Value #B": { "aggregations": [ "lastNotNull" ], "operation": "aggregate" }, "mountpoint": { "aggregations": [ ], "operation": "groupby" } } } }, { "id": "merge" }, { "id": "calculateField", "options": { "alias": "Used", "binary": { "left": "Value #A (lastNotNull)", "operator": "-", "reducer": "sum", "right": "Value #B (lastNotNull)" }, "mode": "binary", "reduce": { "reducer": "sum" } } }, { "id": "calculateField", "options": { "alias": "Used, %", "binary": { "left": "Used", "operator": "/", "reducer": "sum", "right": "Value #A (lastNotNull)" }, "mode": "binary", "reduce": { "reducer": "sum" } } }, { "id": "organize", "options": { "excludeByName": { }, "indexByName": { }, "renameByName": { "Value #A (lastNotNull)": "Size", "Value #B (lastNotNull)": "Available", "mountpoint": "Mounted on" } } }, { "id": "sortBy", "options": { "fields": { }, "sort": [ { "field": "Mounted on" } ] } } ], "type": "table" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 26 }, "id": 10, "panels": [ ], "title": "Network", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "Network received (bits/s)", "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" }, "min": 0, "unit": "bps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 27 }, "id": 11, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_network_receive_bytes_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device!=\"lo\"}[$__rate_interval]) * 8", "intervalFactor": 1, "legendFormat": "{{device}}" } ], "title": "Network Received", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "Network transmitted (bits/s)", "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0 }, "min": 0, "unit": "bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 27 }, "id": 12, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_network_transmit_bytes_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device!=\"lo\"}[$__rate_interval]) * 8", "intervalFactor": 1, "legendFormat": "{{device}}" } ], "title": "Network Transmitted", "type": "timeseries" } ], "refresh": "30s", "schemaVersion": 39, "tags": [ "node-exporter-mixin" ], "templating": { "list": [ { "name": "datasource", "query": "prometheus", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 2, "label": "Cluster", "name": "cluster", "query": "label_values(node_uname_info{job=\"node-exporter\", sysname!=\"Darwin\"}, cluster)", "refresh": 2, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "label": "Instance", "name": "instance", "query": "label_values(node_uname_info{job=\"node-exporter\", cluster=\"$cluster\", sysname!=\"Darwin\"}, instance)", "refresh": 2, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "utc", "title": "Node Exporter / AIX", "uid": "7e0a61e486f727d763fb1d86fdd629c2" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-nodes-aix namespace: monitoring - apiVersion: v1 data: nodes-darwin.json: |- { "graphTooltip": 1, "panels": [ { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 1, "panels": [ ], "title": "CPU", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "stacking": { "mode": "normal" } }, "max": 1, "min": 0, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 1 }, "id": 2, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "(\n (1 - sum without (mode) (rate(node_cpu_seconds_total{job=\"node-exporter\", mode=~\"idle|iowait|steal\", instance=\"$instance\", cluster=\"$cluster\"}[$__rate_interval])))\n/ ignoring(cpu) group_left\n count without (cpu, mode) (node_cpu_seconds_total{job=\"node-exporter\", mode=\"idle\", instance=\"$instance\", cluster=\"$cluster\"})\n)\n", "intervalFactor": 5, "legendFormat": "{{cpu}}" } ], "title": "CPU Usage", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" }, "min": 0, "unit": "short" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 1 }, "id": 3, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_load1{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "1m load average" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_load5{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "5m load average" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_load15{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "15m load average" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "count(node_cpu_seconds_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", mode=\"idle\"})", "legendFormat": "logical cores" } ], "title": "Load Average", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 8 }, "id": 4, "title": "Memory", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "stacking": { "mode": "none" } }, "min": 0, "unit": "bytes" } }, "gridPos": { "h": 7, "w": 18, "x": 0, "y": 9 }, "id": 5, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_memory_total_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "Physical Memory" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "(\n node_memory_internal_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} -\n node_memory_purgeable_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} +\n node_memory_wired_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} +\n node_memory_compressed_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}\n)\n", "legendFormat": "Memory Used" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "(\n node_memory_internal_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"} -\n node_memory_purgeable_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}\n)\n", "legendFormat": "App Memory" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_memory_wired_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "Wired Memory" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_memory_compressed_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "Compressed" } ], "title": "Memory Usage", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "max": 100, "min": 0, "thresholds": { "steps": [ { "color": "rgba(50, 172, 45, 0.97)" }, { "color": "rgba(237, 129, 40, 0.89)", "value": 80 }, { "color": "rgba(245, 54, 54, 0.9)", "value": 90 } ] }, "unit": "percent" } }, "gridPos": { "h": 7, "w": 6, "x": 18, "y": 9 }, "id": 6, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "(\n (\n avg(node_memory_internal_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}) -\n avg(node_memory_purgeable_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}) +\n avg(node_memory_wired_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}) +\n avg(node_memory_compressed_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"})\n ) /\n avg(node_memory_total_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"})\n)\n*\n100\n" } ], "title": "Memory Usage", "type": "gauge" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 18 }, "id": 7, "panels": [ ], "title": "Disk", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" }, "min": 0 }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/ read| written/" }, "properties": [ { "id": "unit", "value": "Bps" } ] }, { "matcher": { "id": "byRegexp", "options": "/ io time/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 19 }, "id": 8, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_disk_read_bytes_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\"}[$__rate_interval])", "intervalFactor": 1, "legendFormat": "{{device}} read" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_disk_written_bytes_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\"}[$__rate_interval])", "intervalFactor": 1, "legendFormat": "{{device}} written" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_disk_io_time_seconds_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\"}[$__rate_interval])", "intervalFactor": 1, "legendFormat": "{{device}} io time" } ], "title": "Disk I/O", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "thresholds": { "steps": [ { "color": "green" }, { "color": "yellow", "value": 0.8 }, { "color": "red", "value": 0.9 } ] }, "unit": "decbytes" }, "overrides": [ { "matcher": { "id": "byName", "options": "Mounted on" }, "properties": [ { "id": "custom.width", "value": 260 } ] }, { "matcher": { "id": "byName", "options": "Size" }, "properties": [ { "id": "custom.width", "value": 93 } ] }, { "matcher": { "id": "byName", "options": "Used" }, "properties": [ { "id": "custom.width", "value": 72 } ] }, { "matcher": { "id": "byName", "options": "Available" }, "properties": [ { "id": "custom.width", "value": 88 } ] }, { "matcher": { "id": "byName", "options": "Used, %" }, "properties": [ { "id": "unit", "value": "percentunit" }, { "id": "custom.cellOptions", "value": { "type": "gauge" } }, { "id": "max", "value": 1 }, { "id": "min", "value": 0 } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 19 }, "id": 9, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "max by (mountpoint) (node_filesystem_size_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", fstype!=\"\", mountpoint!=\"\"})\n", "format": "table", "instant": true, "legendFormat": "" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "max by (mountpoint) (node_filesystem_avail_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", fstype!=\"\", mountpoint!=\"\"})\n", "format": "table", "instant": true, "legendFormat": "" } ], "title": "Disk Space Usage", "transformations": [ { "id": "groupBy", "options": { "fields": { "Value #A": { "aggregations": [ "lastNotNull" ], "operation": "aggregate" }, "Value #B": { "aggregations": [ "lastNotNull" ], "operation": "aggregate" }, "mountpoint": { "aggregations": [ ], "operation": "groupby" } } } }, { "id": "merge" }, { "id": "calculateField", "options": { "alias": "Used", "binary": { "left": "Value #A (lastNotNull)", "operator": "-", "reducer": "sum", "right": "Value #B (lastNotNull)" }, "mode": "binary", "reduce": { "reducer": "sum" } } }, { "id": "calculateField", "options": { "alias": "Used, %", "binary": { "left": "Used", "operator": "/", "reducer": "sum", "right": "Value #A (lastNotNull)" }, "mode": "binary", "reduce": { "reducer": "sum" } } }, { "id": "organize", "options": { "excludeByName": { }, "indexByName": { }, "renameByName": { "Value #A (lastNotNull)": "Size", "Value #B (lastNotNull)": "Available", "mountpoint": "Mounted on" } } }, { "id": "sortBy", "options": { "fields": { }, "sort": [ { "field": "Mounted on" } ] } } ], "type": "table" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 26 }, "id": 10, "panels": [ ], "title": "Network", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "Network received (bits/s)", "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" }, "min": 0, "unit": "bps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 27 }, "id": 11, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_network_receive_bytes_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device!=\"lo\"}[$__rate_interval]) * 8", "intervalFactor": 1, "legendFormat": "{{device}}" } ], "title": "Network Received", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "Network transmitted (bits/s)", "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0 }, "min": 0, "unit": "bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 27 }, "id": 12, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_network_transmit_bytes_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device!=\"lo\"}[$__rate_interval]) * 8", "intervalFactor": 1, "legendFormat": "{{device}}" } ], "title": "Network Transmitted", "type": "timeseries" } ], "refresh": "30s", "schemaVersion": 39, "tags": [ "node-exporter-mixin" ], "templating": { "list": [ { "name": "datasource", "query": "prometheus", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 2, "label": "Cluster", "name": "cluster", "query": "label_values(node_uname_info{job=\"node-exporter\", sysname=\"Darwin\"}, cluster)", "refresh": 2, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "label": "Instance", "name": "instance", "query": "label_values(node_uname_info{job=\"node-exporter\", cluster=\"$cluster\", sysname=\"Darwin\"}, instance)", "refresh": 2, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "utc", "title": "Node Exporter / MacOS", "uid": "629701ea43bf69291922ea45f4a87d37" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-nodes-darwin namespace: monitoring - apiVersion: v1 data: nodes.json: |- { "graphTooltip": 1, "panels": [ { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 1, "panels": [ ], "title": "CPU", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "stacking": { "mode": "normal" } }, "max": 1, "min": 0, "unit": "percentunit" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 1 }, "id": 2, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "(\n (1 - sum without (mode) (rate(node_cpu_seconds_total{job=\"node-exporter\", mode=~\"idle|iowait|steal\", instance=\"$instance\", cluster=\"$cluster\"}[$__rate_interval])))\n/ ignoring(cpu) group_left\n count without (cpu, mode) (node_cpu_seconds_total{job=\"node-exporter\", mode=\"idle\", instance=\"$instance\", cluster=\"$cluster\"})\n)\n", "intervalFactor": 5, "legendFormat": "{{cpu}}" } ], "title": "CPU Usage", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" }, "min": 0, "unit": "short" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 1 }, "id": 3, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_load1{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "1m load average" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_load5{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "5m load average" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_load15{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "15m load average" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "count(node_cpu_seconds_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", mode=\"idle\"})", "legendFormat": "logical cores" } ], "title": "Load Average", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 8 }, "id": 4, "title": "Memory", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "stacking": { "mode": "normal" } }, "min": 0, "unit": "bytes" } }, "gridPos": { "h": 7, "w": 18, "x": 0, "y": 9 }, "id": 5, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "(\n node_memory_MemTotal_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}\n-\n node_memory_MemFree_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}\n-\n node_memory_Buffers_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}\n-\n node_memory_Cached_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}\n)\n", "legendFormat": "memory used" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_memory_Buffers_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "memory buffers" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_memory_Cached_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "memory cached" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "node_memory_MemFree_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}", "legendFormat": "memory free" } ], "title": "Memory Usage", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "max": 100, "min": 0, "thresholds": { "steps": [ { "color": "rgba(50, 172, 45, 0.97)" }, { "color": "rgba(237, 129, 40, 0.89)", "value": 80 }, { "color": "rgba(245, 54, 54, 0.9)", "value": 90 } ] }, "unit": "percent" } }, "gridPos": { "h": 7, "w": 6, "x": 18, "y": 9 }, "id": 6, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "100 -\n(\n avg(node_memory_MemAvailable_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"}) /\n avg(node_memory_MemTotal_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\"})\n* 100\n)\n" } ], "title": "Memory Usage", "type": "gauge" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 18 }, "id": 7, "panels": [ ], "title": "Disk", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" }, "min": 0 }, "overrides": [ { "matcher": { "id": "byRegexp", "options": "/ read| written/" }, "properties": [ { "id": "unit", "value": "Bps" } ] }, { "matcher": { "id": "byRegexp", "options": "/ io time/" }, "properties": [ { "id": "unit", "value": "percentunit" } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 19 }, "id": 8, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_disk_read_bytes_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\"}[$__rate_interval])", "intervalFactor": 1, "legendFormat": "{{device}} read" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_disk_written_bytes_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\"}[$__rate_interval])", "intervalFactor": 1, "legendFormat": "{{device}} written" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_disk_io_time_seconds_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)\"}[$__rate_interval])", "intervalFactor": 1, "legendFormat": "{{device}} io time" } ], "title": "Disk I/O", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "thresholds": { "steps": [ { "color": "green" }, { "color": "yellow", "value": 0.8 }, { "color": "red", "value": 0.9 } ] }, "unit": "decbytes" }, "overrides": [ { "matcher": { "id": "byName", "options": "Mounted on" }, "properties": [ { "id": "custom.width", "value": 260 } ] }, { "matcher": { "id": "byName", "options": "Size" }, "properties": [ { "id": "custom.width", "value": 93 } ] }, { "matcher": { "id": "byName", "options": "Used" }, "properties": [ { "id": "custom.width", "value": 72 } ] }, { "matcher": { "id": "byName", "options": "Available" }, "properties": [ { "id": "custom.width", "value": 88 } ] }, { "matcher": { "id": "byName", "options": "Used, %" }, "properties": [ { "id": "unit", "value": "percentunit" }, { "id": "custom.cellOptions", "value": { "type": "gauge" } }, { "id": "max", "value": 1 }, { "id": "min", "value": 0 } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 19 }, "id": 9, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "max by (mountpoint) (node_filesystem_size_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", fstype!=\"\", mountpoint!=\"\"})\n", "format": "table", "instant": true, "legendFormat": "" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "max by (mountpoint) (node_filesystem_avail_bytes{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", fstype!=\"\", mountpoint!=\"\"})\n", "format": "table", "instant": true, "legendFormat": "" } ], "title": "Disk Space Usage", "transformations": [ { "id": "groupBy", "options": { "fields": { "Value #A": { "aggregations": [ "lastNotNull" ], "operation": "aggregate" }, "Value #B": { "aggregations": [ "lastNotNull" ], "operation": "aggregate" }, "mountpoint": { "aggregations": [ ], "operation": "groupby" } } } }, { "id": "merge" }, { "id": "calculateField", "options": { "alias": "Used", "binary": { "left": "Value #A (lastNotNull)", "operator": "-", "reducer": "sum", "right": "Value #B (lastNotNull)" }, "mode": "binary", "reduce": { "reducer": "sum" } } }, { "id": "calculateField", "options": { "alias": "Used, %", "binary": { "left": "Used", "operator": "/", "reducer": "sum", "right": "Value #A (lastNotNull)" }, "mode": "binary", "reduce": { "reducer": "sum" } } }, { "id": "organize", "options": { "excludeByName": { }, "indexByName": { }, "renameByName": { "Value #A (lastNotNull)": "Size", "Value #B (lastNotNull)": "Available", "mountpoint": "Mounted on" } } }, { "id": "sortBy", "options": { "fields": { }, "sort": [ { "field": "Mounted on" } ] } } ], "type": "table" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 26 }, "id": 10, "panels": [ ], "title": "Network", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "Network received (bits/s)", "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" }, "min": 0, "unit": "bps" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 27 }, "id": 11, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_network_receive_bytes_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device!=\"lo\"}[$__rate_interval]) * 8", "intervalFactor": 1, "legendFormat": "{{device}}" } ], "title": "Network Received", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "Network transmitted (bits/s)", "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0 }, "min": 0, "unit": "bps" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 27 }, "id": 12, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(node_network_transmit_bytes_total{job=\"node-exporter\", instance=\"$instance\", cluster=\"$cluster\", device!=\"lo\"}[$__rate_interval]) * 8", "intervalFactor": 1, "legendFormat": "{{device}}" } ], "title": "Network Transmitted", "type": "timeseries" } ], "refresh": "30s", "schemaVersion": 39, "tags": [ "node-exporter-mixin" ], "templating": { "list": [ { "name": "datasource", "query": "prometheus", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 2, "label": "Cluster", "name": "cluster", "query": "label_values(node_uname_info{job=\"node-exporter\", sysname!=\"Darwin\"}, cluster)", "refresh": 2, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "label": "Instance", "name": "instance", "query": "label_values(node_uname_info{job=\"node-exporter\", cluster=\"$cluster\", sysname!=\"Darwin\"}, instance)", "refresh": 2, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "utc", "title": "Node Exporter / Nodes", "uid": "7d57716318ee0dddbac5a7f451fb7753" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-nodes namespace: monitoring - apiVersion: v1 data: persistentvolumesusage.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "bytes" } }, "gridPos": { "h": 7, "w": 18, "y": 0 }, "id": 1, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(\n sum without(instance, node) (topk(1, (kubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n -\n sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n)\n", "legendFormat": "Used Space" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n", "legendFormat": "Free Space" } ], "title": "Volume Space Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "max": 100, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": 0 }, { "color": "orange", "value": 80 }, { "color": "red", "value": 90 } ] }, "unit": "percent" } }, "gridPos": { "h": 7, "w": 6, "x": 18, "y": 0 }, "id": 2, "interval": "1m", "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "max without(instance,node) (\n(\n topk(1, kubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n -\n topk(1, kubelet_volume_stats_available_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n)\n/\ntopk(1, kubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n* 100)\n", "instant": true } ], "title": "Volume Space Usage", "type": "gauge" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "none" } }, "gridPos": { "h": 7, "w": 18, "y": 7 }, "id": 3, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))", "legendFormat": "Used inodes" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "(\n sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n -\n sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n)\n", "legendFormat": "Free inodes" } ], "title": "Volume inodes Usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "max": 100, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": 0 }, { "color": "orange", "value": 80 }, { "color": "red", "value": 90 } ] }, "unit": "percent" } }, "gridPos": { "h": 7, "w": 6, "x": 18, "y": 7 }, "id": 4, "interval": "1m", "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "max without(instance,node) (\ntopk(1, kubelet_volume_stats_inodes_used{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n/\ntopk(1, kubelet_volume_stats_inodes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n* 100)\n", "instant": true } ], "title": "Volume inodes Usage", "type": "gauge" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(kubelet_volume_stats_capacity_bytes{job=\"kubelet\", metrics_path=\"/metrics\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "Namespace", "name": "namespace", "query": "label_values(kubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\"}, namespace)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "PersistentVolumeClaim", "name": "volume", "query": "label_values(kubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\"}, persistentvolumeclaim)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Persistent Volumes", "uid": "919b92a8e8041bd567af9edab12c840c" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-persistentvolumesusage namespace: monitoring - apiVersion: v1 data: pod-total.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "displayName": "$pod", "max": 10000000000, "min": 0, "thresholds": { "steps": [ { "color": "dark-green", "index": 0, "value": null }, { "color": "dark-yellow", "index": 1, "value": 5000000000 }, { "color": "dark-red", "index": 2, "value": 7000000000 } ] }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))", "legendFormat": "__auto" } ], "title": "Current Rate of Bytes Received", "type": "gauge" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "displayName": "$pod", "max": 10000000000, "min": 0, "thresholds": { "steps": [ { "color": "dark-green", "index": 0, "value": null }, { "color": "dark-yellow", "index": 1, "value": 5000000000 }, { "color": "dark-red", "index": 2, "value": 7000000000 } ] }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 0 }, "id": 2, "interval": "1m", "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))", "legendFormat": "__auto" } ], "title": "Current Rate of Bytes Transmitted", "type": "gauge" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "binBps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 9 }, "id": 3, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Receive Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "binBps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 9 }, "id": 4, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Transmit Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 18 }, "id": 5, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Rate of Received Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 18 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 27 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Rate of Received Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "showPoints": "never" }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 27 }, "id": 8, "interval": "1m", "options": { "legend": { "asTable": true, "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets Dropped", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "allValue": ".+", "current": { "selected": false, "text": "kube-system", "value": "kube-system" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "label": "namespace", "name": "namespace", "query": "label_values(container_network_receive_packets_total{cluster=\"$cluster\"}, namespace)", "refresh": 2, "sort": 1, "type": "query" }, { "current": { "selected": false, "text": "kube-system", "value": "kube-system" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "pod", "name": "pod", "query": "label_values(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}, pod)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Networking / Pod", "uid": "7a18067ce943a40ae25454675c19ff5c" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-pod-total namespace: monitoring - apiVersion: v1 data: prometheus-remote-write.json: |- { "panels": [ { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 1, "panels": [ ], "title": "Timestamps", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never" }, "unit": "short" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 1 }, "id": 2, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "(\n prometheus_remote_storage_highest_timestamp_in_seconds{cluster=~\"$cluster\", instance=~\"$instance\"}\n-\n ignoring(remote_name, url) group_right(instance) (prometheus_remote_storage_queue_highest_sent_timestamp_seconds{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"} != 0)\n)\n", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}::{{instance}} {{remote_name}}:{{url}}" } ], "title": "Highest Timestamp In vs. Highest Timestamp Sent", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never" }, "unit": "short" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 1 }, "id": 3, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "clamp_min(\n rate(prometheus_remote_storage_highest_timestamp_in_seconds{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])\n-\n ignoring (remote_name, url) group_right(instance) rate(prometheus_remote_storage_queue_highest_sent_timestamp_seconds{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}[5m])\n, 0)\n", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}:{{instance}} {{remote_name}}:{{url}}" } ], "title": "Rate[5m]", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 8 }, "id": 4, "panels": [ ], "title": "Samples", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never" }, "unit": "short" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 9 }, "id": 5, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(\n prometheus_remote_storage_samples_in_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])\n-\n ignoring(remote_name, url) group_right(instance) (rate(prometheus_remote_storage_succeeded_samples_total{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}[5m]) or rate(prometheus_remote_storage_samples_total{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}[5m]))\n-\n (rate(prometheus_remote_storage_dropped_samples_total{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}[5m]) or rate(prometheus_remote_storage_samples_dropped_total{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}[5m]))\n", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}:{{instance}} {{remote_name}}:{{url}}" } ], "title": "Rate, in vs. succeeded or dropped [5m]", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 16 }, "id": 6, "panels": [ ], "title": "Shards", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never" }, "unit": "short" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 16 }, "id": 7, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "prometheus_remote_storage_shards{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}:{{instance}} {{remote_name}}:{{url}}" } ], "title": "Current Shards", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never" }, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 23 }, "id": 8, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "prometheus_remote_storage_shards_max{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}:{{instance}} {{remote_name}}:{{url}}" } ], "title": "Max Shards", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never" }, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 8, "y": 23 }, "id": 9, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "prometheus_remote_storage_shards_min{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}{{instance}} {{remote_name}}:{{url}}" } ], "title": "Min Shards", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never" }, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 16, "y": 23 }, "id": 10, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "prometheus_remote_storage_shards_desired{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}:{{instance}} {{remote_name}}:{{url}}" } ], "title": "Desired Shards", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 24 }, "id": 11, "panels": [ ], "title": "Shard Details", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never" }, "unit": "short" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 25 }, "id": 12, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "prometheus_remote_storage_shard_capacity{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}:{{instance}} {{remote_name}}:{{url}}" } ], "title": "Shard Capacity", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never" }, "unit": "short" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 25 }, "id": 13, "options": { "tooltip": { "mode": "multi" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "prometheus_remote_storage_pending_samples{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"} or prometheus_remote_storage_samples_pending{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}:{{instance}} {{remote_name}}:{{url}}" } ], "title": "Pending Samples", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 32 }, "id": 14, "panels": [ ], "title": "Segments", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" }, "unit": "none" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 33 }, "id": 15, "options": { "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "prometheus_tsdb_wal_segment_current{cluster=~\"$cluster\", instance=~\"$instance\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}:{{instance}}" } ], "title": "TSDB Current Segment", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" }, "unit": "none" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 33 }, "id": 16, "options": { "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "prometheus_wal_watcher_current_segment{cluster=~\"$cluster\", instance=~\"$instance\"}", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}:{{instance}} {{consumer}}" } ], "title": "Remote Write Current Segment", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 40 }, "id": 17, "panels": [ ], "title": "Misc. Rates", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" } } }, "gridPos": { "h": 7, "w": 6, "x": 0, "y": 41 }, "id": 18, "options": { "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(prometheus_remote_storage_dropped_samples_total{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}[5m]) or rate(prometheus_remote_storage_samples_dropped_total{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}[5m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}:{{instance}} {{remote_name}}:{{url}}" } ], "title": "Dropped Samples", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" } } }, "gridPos": { "h": 7, "w": 6, "x": 6, "y": 41 }, "id": 19, "options": { "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(prometheus_remote_storage_failed_samples_total{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}[5m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}:{{instance}} {{remote_name}}:{{url}}" } ], "title": "Failed Samples", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" } } }, "gridPos": { "h": 7, "w": 6, "x": 12, "y": 41 }, "id": 20, "options": { "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(prometheus_remote_storage_retried_samples_total{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}[5m]) or rate(prometheus_remote_storage_samples_retried_total{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}[5m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}:{{instance}} {{remote_name}}:{{url}}" } ], "title": "Retried Samples", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 0, "showPoints": "never" } } }, "gridPos": { "h": 7, "w": 6, "x": 18, "y": 41 }, "id": 21, "options": { "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(prometheus_remote_storage_enqueue_retries_total{cluster=~\"$cluster\", instance=~\"$instance\", url=~\"$url\"}[5m])", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{cluster}}:{{instance}} {{remote_name}}:{{url}}" } ], "title": "Enqueue Retries", "type": "timeseries" } ], "schemaVersion": 39, "tags": [ "prometheus-mixin" ], "templating": { "list": [ { "current": { "selected": false, "text": "default", "value": "default" }, "hide": 0, "name": "datasource", "query": "prometheus", "type": "datasource" }, { "current": { "selected": false, "text": "$__all", "value": "$__all" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "name": "cluster", "query": "label_values(prometheus_build_info, cluster)", "refresh": 2, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "includeAll": true, "name": "instance", "query": "label_values(prometheus_build_info{cluster=~\"$cluster\"}, instance)", "refresh": 2, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "includeAll": true, "name": "url", "query": "label_values(prometheus_remote_storage_shards{cluster=~\"$cluster\", instance=~\"$instance\"}, url)", "refresh": 2, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": { "refresh_intervals": [ "60s" ] }, "timezone": "utc", "title": "Prometheus / Remote Write" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-prometheus-remote-write namespace: monitoring - apiVersion: v1 data: prometheus.json: |- { "panels": [ { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 1, "panels": [ ], "title": "Prometheus Stats", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "decimals": 2, "displayName": "", "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "Time" }, "properties": [ { "id": "displayName", "value": "Time" }, { "id": "custom.align", "value": null }, { "id": "custom.hidden", "value": "true" } ] }, { "matcher": { "id": "byName", "options": "cluster" }, "properties": [ { "id": "custom.align", "value": null }, { "id": "unit", "value": "short" }, { "id": "decimals", "value": 2 }, { "id": "displayName", "value": "Cluster" } ] }, { "matcher": { "id": "byName", "options": "job" }, "properties": [ { "id": "custom.align", "value": null }, { "id": "unit", "value": "short" }, { "id": "decimals", "value": 2 }, { "id": "displayName", "value": "Job" } ] }, { "matcher": { "id": "byName", "options": "instance" }, "properties": [ { "id": "displayName", "value": "Instance" }, { "id": "custom.align", "value": null }, { "id": "unit", "value": "short" }, { "id": "decimals", "value": 2 } ] }, { "matcher": { "id": "byName", "options": "version" }, "properties": [ { "id": "displayName", "value": "Version" }, { "id": "custom.align", "value": null }, { "id": "unit", "value": "short" }, { "id": "decimals", "value": 2 } ] }, { "matcher": { "id": "byName", "options": "Value #A" }, "properties": [ { "id": "displayName", "value": "Count" }, { "id": "custom.align", "value": null }, { "id": "unit", "value": "short" }, { "id": "decimals", "value": 2 }, { "id": "custom.hidden", "value": "true" } ] }, { "matcher": { "id": "byName", "options": "Value #B" }, "properties": [ { "id": "displayName", "value": "Uptime" }, { "id": "custom.align", "value": null }, { "id": "unit", "value": "s" } ] } ] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 1 }, "id": 2, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "count by (cluster, job, instance, version) (prometheus_build_info{cluster=~\"$cluster\", job=~\"$job\", instance=~\"$instance\"})", "format": "table", "instant": true, "legendFormat": "" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "max by (cluster, job, instance) (time() - process_start_time_seconds{cluster=~\"$cluster\", job=~\"$job\", instance=~\"$instance\"})", "format": "table", "instant": true, "legendFormat": "" } ], "title": "Prometheus Stats", "type": "table" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 8 }, "id": 3, "panels": [ ], "title": "Discovery", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never" }, "min": 0, "unit": "ms" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 9 }, "id": 4, "options": { "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum(rate(prometheus_target_sync_length_seconds_sum{cluster=~\"$cluster\",job=~\"$job\",instance=~\"$instance\"}[5m])) by (cluster, job, scrape_job, instance) * 1e3", "format": "time_series", "legendFormat": "{{cluster}}:{{job}}:{{instance}}:{{scrape_job}}" } ], "title": "Target Sync", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "lineWidth": 0, "showPoints": "never", "stacking": { "mode": "normal" } }, "min": 0, "unit": "short" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 9 }, "id": 5, "options": { "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum by (cluster, job, instance) (prometheus_sd_discovered_targets{cluster=~\"$cluster\", job=~\"$job\",instance=~\"$instance\"})", "format": "time_series", "legendFormat": "{{cluster}}:{{job}}:{{instance}}" } ], "title": "Targets", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 16 }, "id": 6, "panels": [ ], "title": "Retrieval", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never" }, "min": 0, "unit": "ms" } }, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 17 }, "id": 7, "options": { "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(prometheus_target_interval_length_seconds_sum{cluster=~\"$cluster\", job=~\"$job\",instance=~\"$instance\"}[5m]) / rate(prometheus_target_interval_length_seconds_count{cluster=~\"$cluster\", job=~\"$job\",instance=~\"$instance\"}[5m]) * 1e3", "format": "time_series", "legendFormat": "{{cluster}}:{{job}}:{{instance}} {{interval}} configured" } ], "title": "Average Scrape Interval Duration", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "lineWidth": 0, "showPoints": "never", "stacking": { "mode": "normal" } }, "min": 0, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 8, "y": 17 }, "id": 8, "options": { "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum by (cluster, job, instance) (rate(prometheus_target_scrapes_exceeded_body_size_limit_total{cluster=~\"$cluster\",job=~\"$job\",instance=~\"$instance\"}[1m]))", "format": "time_series", "legendFormat": "exceeded body size limit: {{cluster}} {{job}} {{instance}}" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum by (cluster, job, instance) (rate(prometheus_target_scrapes_exceeded_sample_limit_total{cluster=~\"$cluster\",job=~\"$job\",instance=~\"$instance\"}[1m]))", "format": "time_series", "legendFormat": "exceeded sample limit: {{cluster}} {{job}} {{instance}}" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum by (cluster, job, instance) (rate(prometheus_target_scrapes_sample_duplicate_timestamp_total{cluster=~\"$cluster\",job=~\"$job\",instance=~\"$instance\"}[1m]))", "format": "time_series", "legendFormat": "duplicate timestamp: {{cluster}} {{job}} {{instance}}" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum by (cluster, job, instance) (rate(prometheus_target_scrapes_sample_out_of_bounds_total{cluster=~\"$cluster\",job=~\"$job\",instance=~\"$instance\"}[1m]))", "format": "time_series", "legendFormat": "out of bounds: {{cluster}} {{job}} {{instance}}" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "sum by (cluster, job, instance) (rate(prometheus_target_scrapes_sample_out_of_order_total{cluster=~\"$cluster\",job=~\"$job\",instance=~\"$instance\"}[1m]))", "format": "time_series", "legendFormat": "out of order: {{cluster}} {{job}} {{instance}}" } ], "title": "Scrape failures", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "lineWidth": 0, "showPoints": "never", "stacking": { "mode": "normal" } }, "min": 0, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 16, "y": 17 }, "id": 9, "options": { "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(prometheus_tsdb_head_samples_appended_total{cluster=~\"$cluster\", job=~\"$job\",instance=~\"$instance\"}[5m])", "format": "time_series", "legendFormat": "{{cluster}} {{job}} {{instance}}" } ], "title": "Appended Samples", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 24 }, "id": 10, "panels": [ ], "title": "Storage", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "lineWidth": 0, "showPoints": "never", "stacking": { "mode": "normal" } }, "min": 0, "unit": "short" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 25 }, "id": 11, "options": { "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "prometheus_tsdb_head_series{cluster=~\"$cluster\",job=~\"$job\",instance=~\"$instance\"}", "format": "time_series", "legendFormat": "{{cluster}} {{job}} {{instance}} head series" } ], "title": "Head Series", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "lineWidth": 0, "showPoints": "never", "stacking": { "mode": "normal" } }, "min": 0, "unit": "short" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 25 }, "id": 12, "options": { "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "prometheus_tsdb_head_chunks{cluster=~\"$cluster\",job=~\"$job\",instance=~\"$instance\"}", "format": "time_series", "legendFormat": "{{cluster}} {{job}} {{instance}} head chunks" } ], "title": "Head Chunks", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 32 }, "id": 13, "panels": [ ], "title": "Query", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "lineWidth": 0, "showPoints": "never", "stacking": { "mode": "normal" } }, "min": 0, "unit": "short" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 33 }, "id": 14, "options": { "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "rate(prometheus_engine_query_duration_seconds_count{cluster=~\"$cluster\",job=~\"$job\",instance=~\"$instance\",slice=\"inner_eval\"}[5m])", "format": "time_series", "legendFormat": "{{cluster}} {{job}} {{instance}}" } ], "title": "Query Rate", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "$datasource" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 100, "lineWidth": 0, "showPoints": "never", "stacking": { "mode": "normal" } }, "min": 0, "unit": "ms" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 33 }, "id": 15, "options": { "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "$datasource" }, "expr": "max by (slice) (prometheus_engine_query_duration_seconds{quantile=\"0.9\",cluster=~\"$cluster\", job=~\"$job\",instance=~\"$instance\"}) * 1e3", "format": "time_series", "legendFormat": "{{slice}}" } ], "title": "Stage Duration", "type": "timeseries" } ], "schemaVersion": 39, "tags": [ "prometheus-mixin" ], "templating": { "list": [ { "current": { "selected": false, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "type": "datasource" }, { "allValue": ".+", "current": { "selected": false, "text": [ "$__all" ], "value": [ "$__all" ] }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "label": "cluster", "multi": true, "name": "cluster", "query": "label_values(prometheus_build_info{job=\"prometheus-k8s\",namespace=\"monitoring\"}, cluster)", "refresh": 2, "sort": 2, "type": "query" }, { "allValue": ".+", "datasource": { "type": "prometheus", "uid": "${datasource}" }, "includeAll": true, "label": "job", "multi": true, "name": "job", "query": "label_values(prometheus_build_info{cluster=~\"$cluster\"}, job)", "refresh": 2, "sort": 2, "type": "query" }, { "allValue": ".+", "datasource": { "type": "prometheus", "uid": "${datasource}" }, "includeAll": true, "label": "instance", "multi": true, "name": "instance", "query": "label_values(prometheus_build_info{cluster=~\"$cluster\", job=~\"$job\"}, instance)", "refresh": 2, "sort": 2, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": { "refresh_intervals": [ "60s" ] }, "timezone": "utc", "title": "Prometheus / Overview", "uid": "9fa0d141-d019-4ad7-8bc5-42196ee308bd" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-prometheus namespace: monitoring - apiVersion: v1 data: proxy.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "none" } }, "gridPos": { "h": 7, "w": 4, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(up{cluster=\"$cluster\", job=\"kube-proxy\"})", "instant": true } ], "title": "Up", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 10, "x": 4, "y": 0 }, "id": 2, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(kubeproxy_sync_proxy_rules_duration_seconds_count{cluster=\"$cluster\", job=\"kube-proxy\", instance=~\"$instance\"}[$__rate_interval]))", "legendFormat": "rate" } ], "title": "Rules Sync Rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 10, "x": 14, "y": 0 }, "id": 3, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99,rate(kubeproxy_sync_proxy_rules_duration_seconds_bucket{cluster=\"$cluster\", job=\"kube-proxy\", instance=~\"$instance\"}[$__rate_interval]))", "legendFormat": "{{instance}}" } ], "title": "Rules Sync Latency 99th Quantile", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 7 }, "id": 4, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(kubeproxy_network_programming_duration_seconds_count{cluster=\"$cluster\", job=\"kube-proxy\", instance=~\"$instance\"}[$__rate_interval]))", "legendFormat": "rate" } ], "title": "Network Programming Rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 7 }, "id": 5, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(kubeproxy_network_programming_duration_seconds_bucket{cluster=\"$cluster\", job=\"kube-proxy\", instance=~\"$instance\"}[$__rate_interval])) by (instance, le))", "legendFormat": "{{instance}}" } ], "title": "Network Programming Latency 99th Quantile", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 14 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\",job=\"kube-proxy\", instance=~\"$instance\",code=~\"2..\"}[$__rate_interval]))", "legendFormat": "2xx" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\",job=\"kube-proxy\", instance=~\"$instance\",code=~\"3..\"}[$__rate_interval]))", "legendFormat": "3xx" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\",job=\"kube-proxy\", instance=~\"$instance\",code=~\"4..\"}[$__rate_interval]))", "legendFormat": "4xx" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\",job=\"kube-proxy\", instance=~\"$instance\",code=~\"5..\"}[$__rate_interval]))", "legendFormat": "5xx" } ], "title": "Kube API Request Rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 16, "x": 8, "y": 14 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\"$cluster\", job=\"kube-proxy\",instance=~\"$instance\",verb=\"POST\"}[$__rate_interval])) by (verb, le))", "legendFormat": "{{verb}}" } ], "title": "Post Request Latency 99th Quantile", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 21 }, "id": 8, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\"$cluster\", job=\"kube-proxy\", instance=~\"$instance\", verb=\"GET\"}[$__rate_interval])) by (verb, le))", "legendFormat": "{{verb}}" } ], "title": "Get Request Latency 99th Quantile", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "bytes" } }, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 28 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "process_resident_memory_bytes{cluster=\"$cluster\", job=\"kube-proxy\",instance=~\"$instance\"}", "legendFormat": "{{instance}}" } ], "title": "Memory", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 8, "y": 28 }, "id": 10, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "rate(process_cpu_seconds_total{cluster=\"$cluster\", job=\"kube-proxy\",instance=~\"$instance\"}[$__rate_interval])", "legendFormat": "{{instance}}" } ], "title": "CPU usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 16, "y": 28 }, "id": 11, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "go_goroutines{cluster=\"$cluster\", job=\"kube-proxy\",instance=~\"$instance\"}", "legendFormat": "{{instance}}" } ], "title": "Goroutines", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kube-proxy\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "allValue": ".+", "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "label": "instance", "name": "instance", "query": "label_values(up{job=\"kube-proxy\", cluster=\"$cluster\", job=\"kube-proxy\"}, instance)", "refresh": 2, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Proxy", "uid": "632e265de029684c40b21cb76bca4f94" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-proxy namespace: monitoring - apiVersion: v1 data: scheduler.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "unit": "none" } }, "gridPos": { "h": 7, "w": 4, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "colorMode": "none" }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(up{cluster=\"$cluster\", job=\"kube-scheduler\"})", "instant": true } ], "title": "Up", "type": "stat" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 10, "x": 4, "y": 0 }, "id": 2, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(scheduler_e2e_scheduling_duration_seconds_count{cluster=\"$cluster\", job=\"kube-scheduler\", instance=~\"$instance\"}[$__rate_interval])) by (cluster, instance)", "legendFormat": "{{cluster}} {{instance}} e2e" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(scheduler_binding_duration_seconds_count{cluster=\"$cluster\", job=\"kube-scheduler\", instance=~\"$instance\"}[$__rate_interval])) by (cluster, instance)", "legendFormat": "{{cluster}} {{instance}} binding" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(scheduler_scheduling_algorithm_duration_seconds_count{cluster=\"$cluster\", job=\"kube-scheduler\", instance=~\"$instance\"}[$__rate_interval])) by (cluster, instance)", "legendFormat": "{{cluster}} {{instance}} scheduling algorithm" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(scheduler_volume_scheduling_duration_seconds_count{cluster=\"$cluster\", job=\"kube-scheduler\", instance=~\"$instance\"}[$__rate_interval])) by (cluster, instance)", "legendFormat": "{{cluster}} {{instance}} volume" } ], "title": "Scheduling Rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 10, "x": 14, "y": 0 }, "id": 3, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(scheduler_e2e_scheduling_duration_seconds_bucket{cluster=\"$cluster\", job=\"kube-scheduler\",instance=~\"$instance\"}[$__rate_interval])) by (cluster, instance, le))", "legendFormat": "{{cluster}} {{instance}} e2e" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(scheduler_binding_duration_seconds_bucket{cluster=\"$cluster\", job=\"kube-scheduler\",instance=~\"$instance\"}[$__rate_interval])) by (cluster, instance, le))", "legendFormat": "{{cluster}} {{instance}} binding" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(scheduler_scheduling_algorithm_duration_seconds_bucket{cluster=\"$cluster\", job=\"kube-scheduler\",instance=~\"$instance\"}[$__rate_interval])) by (cluster, instance, le))", "legendFormat": "{{cluster}} {{instance}} scheduling algorithm" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(scheduler_volume_scheduling_duration_seconds_bucket{cluster=\"$cluster\", job=\"kube-scheduler\",instance=~\"$instance\"}[$__rate_interval])) by (cluster, instance, le))", "legendFormat": "{{cluster}} {{instance}} volume" } ], "title": "Scheduling latency 99th Quantile", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 7 }, "id": 4, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\", job=\"kube-scheduler\", instance=~\"$instance\",code=~\"2..\"}[$__rate_interval]))", "legendFormat": "2xx" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\", job=\"kube-scheduler\", instance=~\"$instance\",code=~\"3..\"}[$__rate_interval]))", "legendFormat": "3xx" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\", job=\"kube-scheduler\", instance=~\"$instance\",code=~\"4..\"}[$__rate_interval]))", "legendFormat": "4xx" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\", job=\"kube-scheduler\", instance=~\"$instance\",code=~\"5..\"}[$__rate_interval]))", "legendFormat": "5xx" } ], "title": "Kube API Request Rate", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "ops" } }, "gridPos": { "h": 7, "w": 16, "x": 8, "y": 7 }, "id": 5, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\"$cluster\", job=\"kube-scheduler\", instance=~\"$instance\", verb=\"POST\"}[$__rate_interval])) by (verb, le))", "legendFormat": "{{verb}}" } ], "title": "Post Request Latency 99th Quantile", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "s" } }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 14 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\"$cluster\", job=\"kube-scheduler\", instance=~\"$instance\", verb=\"GET\"}[$__rate_interval])) by (verb, le))", "legendFormat": "{{verb}}" } ], "title": "Get Request Latency 99th Quantile", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "bytes" } }, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 21 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "process_resident_memory_bytes{cluster=\"$cluster\", job=\"kube-scheduler\", instance=~\"$instance\"}", "legendFormat": "{{instance}}" } ], "title": "Memory", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 8, "y": 21 }, "id": 8, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "rate(process_cpu_seconds_total{cluster=\"$cluster\", job=\"kube-scheduler\", instance=~\"$instance\"}[$__rate_interval])", "legendFormat": "{{instance}}" } ], "title": "CPU usage", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "short" } }, "gridPos": { "h": 7, "w": 8, "x": 16, "y": 21 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "go_goroutines{cluster=\"$cluster\", job=\"kube-scheduler\",instance=~\"$instance\"}", "legendFormat": "{{instance}}" } ], "title": "Goroutines", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(up{job=\"kube-scheduler\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "allValue": ".+", "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "label": "instance", "name": "instance", "query": "label_values(up{job=\"kube-scheduler\", cluster=\"$cluster\"}, instance)", "refresh": 2, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Scheduler", "uid": "2e6b6a3b4bddf1427b3a55aa1311c656" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-scheduler namespace: monitoring - apiVersion: v1 data: workload-total.json: |- { "editable": false, "links": [ { "asDropdown": true, "includeVars": true, "keepTime": true, "tags": [ "kubernetes-mixin" ], "targetBlank": false, "title": "Kubernetes", "type": "dashboards" } ], "panels": [ { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "color": { "fixedColor": "green", "mode": "fixed" }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 0 }, "id": 1, "interval": "1m", "options": { "displayMode": "basic", "showUnfilled": false }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Current Rate of Bytes Received", "type": "bargauge" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "color": { "fixedColor": "green", "mode": "fixed" }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 0 }, "id": 2, "interval": "1m", "options": { "displayMode": "basic", "showUnfilled": false }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Current Rate of Bytes Transmitted", "type": "bargauge" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "color": { "fixedColor": "green", "mode": "fixed" }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 9 }, "id": 3, "interval": "1m", "options": { "displayMode": "basic", "showUnfilled": false }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(avg(rate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Average Rate of Bytes Received", "type": "bargauge" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "color": { "fixedColor": "green", "mode": "fixed" }, "unit": "Bps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 9 }, "id": 4, "interval": "1m", "options": { "displayMode": "basic", "showUnfilled": false }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(avg(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Average Rate of Bytes Transmitted", "type": "bargauge" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "binBps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 18 }, "id": 5, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Receive Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "binBps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 18 }, "id": 6, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Transmit Bandwidth", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 27 }, "id": 7, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_receive_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Rate of Received Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 27 }, "id": 8, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_transmit_packets_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 36 }, "id": 9, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_receive_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Rate of Received Packets Dropped", "type": "timeseries" }, { "datasource": { "type": "datasource", "uid": "-- Mixed --" }, "fieldConfig": { "defaults": { "custom": { "fillOpacity": 10, "showPoints": "never", "spanNulls": true }, "unit": "pps" } }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 36 }, "id": 10, "interval": "1m", "options": { "legend": { "asTable": true, "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single" } }, "pluginVersion": "v11.4.0", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "expr": "sort_desc(sum(rate(container_network_transmit_packets_dropped_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\",namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=~\"$type\"}) by (pod))\n", "legendFormat": "__auto" } ], "title": "Rate of Transmitted Packets Dropped", "type": "timeseries" } ], "refresh": "10s", "schemaVersion": 39, "tags": [ "kubernetes-mixin" ], "templating": { "list": [ { "current": { "selected": true, "text": "default", "value": "default" }, "hide": 0, "label": "Data source", "name": "datasource", "query": "prometheus", "regex": "", "type": "datasource" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "cluster", "name": "cluster", "query": "label_values(kube_pod_info{job=\"kube-state-metrics\"}, cluster)", "refresh": 2, "sort": 1, "type": "query" }, { "allValue": ".+", "current": { "selected": false, "text": "kube-system", "value": "kube-system" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "label": "namespace", "name": "namespace", "query": "label_values(container_network_receive_packets_total{cluster=\"$cluster\"}, namespace)", "refresh": 2, "sort": 1, "type": "query" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "label": "workload", "name": "workload", "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\".+\"}, workload)", "refresh": 2, "sort": 1, "type": "query" }, { "allValue": ".+", "datasource": { "type": "prometheus", "uid": "${datasource}" }, "hide": 0, "includeAll": true, "label": "workload_type", "name": "type", "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\"}, workload_type)", "refresh": 2, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timezone": "UTC", "title": "Kubernetes / Networking / Workload", "uid": "728bf77cc1166d2f3133bf25846876cc" } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboard-workload-total namespace: monitoring kind: ConfigMapList ================================================ FILE: hack/config/monitoring/kube-prometheus/grafana-dashboardSources.yaml ================================================ apiVersion: v1 data: dashboards.yaml: |- { "apiVersion": 1, "providers": [ { "folder": "Default", "folderUid": "", "name": "0", "options": { "path": "/grafana-dashboard-definitions/0" }, "orgId": 1, "type": "file" } ] } kind: ConfigMap metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana-dashboards namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/grafana-deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana namespace: monitoring spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus template: metadata: annotations: checksum/grafana-config: fbb6fa9bc8072c0f9758c30eac1a7ce6 checksum/grafana-dashboardproviders: 4c364bf7811a4eff194596a272550ae5 checksum/grafana-datasources: 34dc6d0eeebe415ac38992ae3518ab8e labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 spec: automountServiceAccountToken: false containers: - env: [] image: grafana/grafana:12.1.0 name: grafana ports: - containerPort: 3000 name: http readinessProbe: httpGet: path: /api/health port: http resources: limits: cpu: 200m memory: 200Mi requests: cpu: 100m memory: 100Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /var/lib/grafana name: grafana-storage readOnly: false - mountPath: /etc/grafana/provisioning/datasources name: grafana-datasources readOnly: false - mountPath: /etc/grafana/provisioning/dashboards name: grafana-dashboards readOnly: false - mountPath: /tmp name: tmp-plugins readOnly: false - mountPath: /grafana-dashboard-definitions/0/alertmanager-overview name: grafana-dashboard-alertmanager-overview readOnly: false - mountPath: /grafana-dashboard-definitions/0/apiserver name: grafana-dashboard-apiserver readOnly: false - mountPath: /grafana-dashboard-definitions/0/cluster-total name: grafana-dashboard-cluster-total readOnly: false - mountPath: /grafana-dashboard-definitions/0/controller-manager name: grafana-dashboard-controller-manager readOnly: false - mountPath: /grafana-dashboard-definitions/0/grafana-overview name: grafana-dashboard-grafana-overview readOnly: false - mountPath: /grafana-dashboard-definitions/0/k8s-resources-cluster name: grafana-dashboard-k8s-resources-cluster readOnly: false - mountPath: /grafana-dashboard-definitions/0/k8s-resources-multicluster name: grafana-dashboard-k8s-resources-multicluster readOnly: false - mountPath: /grafana-dashboard-definitions/0/k8s-resources-namespace name: grafana-dashboard-k8s-resources-namespace readOnly: false - mountPath: /grafana-dashboard-definitions/0/k8s-resources-node name: grafana-dashboard-k8s-resources-node readOnly: false - mountPath: /grafana-dashboard-definitions/0/k8s-resources-pod name: grafana-dashboard-k8s-resources-pod readOnly: false - mountPath: /grafana-dashboard-definitions/0/k8s-resources-windows-cluster name: grafana-dashboard-k8s-resources-windows-cluster readOnly: false - mountPath: /grafana-dashboard-definitions/0/k8s-resources-windows-namespace name: grafana-dashboard-k8s-resources-windows-namespace readOnly: false - mountPath: /grafana-dashboard-definitions/0/k8s-resources-windows-pod name: grafana-dashboard-k8s-resources-windows-pod readOnly: false - mountPath: /grafana-dashboard-definitions/0/k8s-resources-workload name: grafana-dashboard-k8s-resources-workload readOnly: false - mountPath: /grafana-dashboard-definitions/0/k8s-resources-workloads-namespace name: grafana-dashboard-k8s-resources-workloads-namespace readOnly: false - mountPath: /grafana-dashboard-definitions/0/k8s-windows-cluster-rsrc-use name: grafana-dashboard-k8s-windows-cluster-rsrc-use readOnly: false - mountPath: /grafana-dashboard-definitions/0/k8s-windows-node-rsrc-use name: grafana-dashboard-k8s-windows-node-rsrc-use readOnly: false - mountPath: /grafana-dashboard-definitions/0/kubelet name: grafana-dashboard-kubelet readOnly: false - mountPath: /grafana-dashboard-definitions/0/namespace-by-pod name: grafana-dashboard-namespace-by-pod readOnly: false - mountPath: /grafana-dashboard-definitions/0/namespace-by-workload name: grafana-dashboard-namespace-by-workload readOnly: false - mountPath: /grafana-dashboard-definitions/0/node-cluster-rsrc-use name: grafana-dashboard-node-cluster-rsrc-use readOnly: false - mountPath: /grafana-dashboard-definitions/0/node-rsrc-use name: grafana-dashboard-node-rsrc-use readOnly: false - mountPath: /grafana-dashboard-definitions/0/nodes-aix name: grafana-dashboard-nodes-aix readOnly: false - mountPath: /grafana-dashboard-definitions/0/nodes-darwin name: grafana-dashboard-nodes-darwin readOnly: false - mountPath: /grafana-dashboard-definitions/0/nodes name: grafana-dashboard-nodes readOnly: false - mountPath: /grafana-dashboard-definitions/0/persistentvolumesusage name: grafana-dashboard-persistentvolumesusage readOnly: false - mountPath: /grafana-dashboard-definitions/0/pod-total name: grafana-dashboard-pod-total readOnly: false - mountPath: /grafana-dashboard-definitions/0/prometheus-remote-write name: grafana-dashboard-prometheus-remote-write readOnly: false - mountPath: /grafana-dashboard-definitions/0/prometheus name: grafana-dashboard-prometheus readOnly: false - mountPath: /grafana-dashboard-definitions/0/proxy name: grafana-dashboard-proxy readOnly: false - mountPath: /grafana-dashboard-definitions/0/scheduler name: grafana-dashboard-scheduler readOnly: false - mountPath: /grafana-dashboard-definitions/0/workload-total name: grafana-dashboard-workload-total readOnly: false - mountPath: /etc/grafana name: grafana-config readOnly: false nodeSelector: kubernetes.io/os: linux securityContext: fsGroup: 65534 runAsGroup: 65534 runAsNonRoot: true runAsUser: 65534 serviceAccountName: grafana volumes: - emptyDir: {} name: grafana-storage - name: grafana-datasources secret: secretName: grafana-datasources - configMap: name: grafana-dashboards name: grafana-dashboards - emptyDir: medium: Memory name: tmp-plugins - configMap: name: grafana-dashboard-alertmanager-overview name: grafana-dashboard-alertmanager-overview - configMap: name: grafana-dashboard-apiserver name: grafana-dashboard-apiserver - configMap: name: grafana-dashboard-cluster-total name: grafana-dashboard-cluster-total - configMap: name: grafana-dashboard-controller-manager name: grafana-dashboard-controller-manager - configMap: name: grafana-dashboard-grafana-overview name: grafana-dashboard-grafana-overview - configMap: name: grafana-dashboard-k8s-resources-cluster name: grafana-dashboard-k8s-resources-cluster - configMap: name: grafana-dashboard-k8s-resources-multicluster name: grafana-dashboard-k8s-resources-multicluster - configMap: name: grafana-dashboard-k8s-resources-namespace name: grafana-dashboard-k8s-resources-namespace - configMap: name: grafana-dashboard-k8s-resources-node name: grafana-dashboard-k8s-resources-node - configMap: name: grafana-dashboard-k8s-resources-pod name: grafana-dashboard-k8s-resources-pod - configMap: name: grafana-dashboard-k8s-resources-windows-cluster name: grafana-dashboard-k8s-resources-windows-cluster - configMap: name: grafana-dashboard-k8s-resources-windows-namespace name: grafana-dashboard-k8s-resources-windows-namespace - configMap: name: grafana-dashboard-k8s-resources-windows-pod name: grafana-dashboard-k8s-resources-windows-pod - configMap: name: grafana-dashboard-k8s-resources-workload name: grafana-dashboard-k8s-resources-workload - configMap: name: grafana-dashboard-k8s-resources-workloads-namespace name: grafana-dashboard-k8s-resources-workloads-namespace - configMap: name: grafana-dashboard-k8s-windows-cluster-rsrc-use name: grafana-dashboard-k8s-windows-cluster-rsrc-use - configMap: name: grafana-dashboard-k8s-windows-node-rsrc-use name: grafana-dashboard-k8s-windows-node-rsrc-use - configMap: name: grafana-dashboard-kubelet name: grafana-dashboard-kubelet - configMap: name: grafana-dashboard-namespace-by-pod name: grafana-dashboard-namespace-by-pod - configMap: name: grafana-dashboard-namespace-by-workload name: grafana-dashboard-namespace-by-workload - configMap: name: grafana-dashboard-node-cluster-rsrc-use name: grafana-dashboard-node-cluster-rsrc-use - configMap: name: grafana-dashboard-node-rsrc-use name: grafana-dashboard-node-rsrc-use - configMap: name: grafana-dashboard-nodes-aix name: grafana-dashboard-nodes-aix - configMap: name: grafana-dashboard-nodes-darwin name: grafana-dashboard-nodes-darwin - configMap: name: grafana-dashboard-nodes name: grafana-dashboard-nodes - configMap: name: grafana-dashboard-persistentvolumesusage name: grafana-dashboard-persistentvolumesusage - configMap: name: grafana-dashboard-pod-total name: grafana-dashboard-pod-total - configMap: name: grafana-dashboard-prometheus-remote-write name: grafana-dashboard-prometheus-remote-write - configMap: name: grafana-dashboard-prometheus name: grafana-dashboard-prometheus - configMap: name: grafana-dashboard-proxy name: grafana-dashboard-proxy - configMap: name: grafana-dashboard-scheduler name: grafana-dashboard-scheduler - configMap: name: grafana-dashboard-workload-total name: grafana-dashboard-workload-total - name: grafana-config secret: secretName: grafana-config ================================================ FILE: hack/config/monitoring/kube-prometheus/grafana-networkPolicy.yaml ================================================ apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana namespace: monitoring spec: egress: - {} ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: prometheus ports: - port: 3000 protocol: TCP podSelector: matchLabels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus policyTypes: - Egress - Ingress ================================================ FILE: hack/config/monitoring/kube-prometheus/grafana-prometheusRule.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 prometheus: k8s role: alert-rules name: grafana-rules namespace: monitoring spec: groups: - name: GrafanaAlerts rules: - alert: GrafanaRequestsFailing annotations: message: '{{ $labels.namespace }}/{{ $labels.job }}/{{ $labels.handler }} is experiencing {{ $value | humanize }}% errors' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/grafana/grafanarequestsfailing expr: | 100 * sum without (status_code) (namespace_job_handler_statuscode:grafana_http_request_duration_seconds_count:rate5m{handler!~"/api/datasources/proxy/:id.*|/api/ds/query|/api/tsdb/query", status_code=~"5.."}) / sum without (status_code) (namespace_job_handler_statuscode:grafana_http_request_duration_seconds_count:rate5m{handler!~"/api/datasources/proxy/:id.*|/api/ds/query|/api/tsdb/query"}) > 50 for: 5m labels: severity: warning - name: grafana_rules rules: - expr: | sum by (namespace, job, handler, status_code) (rate(grafana_http_request_duration_seconds_count[5m])) record: namespace_job_handler_statuscode:grafana_http_request_duration_seconds_count:rate5m ================================================ FILE: hack/config/monitoring/kube-prometheus/grafana-service.yaml ================================================ apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana namespace: monitoring spec: ports: - name: http port: 3000 targetPort: http selector: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus ================================================ FILE: hack/config/monitoring/kube-prometheus/grafana-serviceAccount.yaml ================================================ apiVersion: v1 automountServiceAccountToken: false kind: ServiceAccount metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/grafana-serviceMonitor.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/component: grafana app.kubernetes.io/name: grafana app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 12.1.0 name: grafana namespace: monitoring spec: endpoints: - interval: 15s port: http selector: matchLabels: app.kubernetes.io/name: grafana ================================================ FILE: hack/config/monitoring/kube-prometheus/kubePrometheus-prometheusRule.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-prometheus app.kubernetes.io/part-of: kube-prometheus prometheus: k8s role: alert-rules name: kube-prometheus-rules namespace: monitoring spec: groups: - name: general.rules rules: - alert: TargetDown annotations: description: '{{ printf "%.4g" $value }}% of the {{ $labels.job }}/{{ $labels.service }} targets in {{ $labels.namespace }} namespace are down.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/general/targetdown summary: One or more targets are unreachable. expr: 100 * (count(up == 0) BY (cluster, job, namespace, service) / count(up) BY (cluster, job, namespace, service)) > 10 for: 10m labels: severity: warning - alert: Watchdog annotations: description: | This is an alert meant to ensure that the entire alerting pipeline is functional. This alert is always firing, therefore it should always be firing in Alertmanager and always fire against a receiver. There are integrations with various notification mechanisms that send a notification when this alert is not firing. For example the "DeadMansSnitch" integration in PagerDuty. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/general/watchdog summary: An alert that should always be firing to certify that Alertmanager is working properly. expr: vector(1) labels: severity: none - alert: InfoInhibitor annotations: description: | This is an alert that is used to inhibit info alerts. By themselves, the info-level alerts are sometimes very noisy, but they are relevant when combined with other alerts. This alert fires whenever there's a severity="info" alert, and stops firing when another alert with a severity of 'warning' or 'critical' starts firing on the same namespace. This alert should be routed to a null receiver and configured to inhibit alerts with severity="info". runbook_url: https://runbooks.prometheus-operator.dev/runbooks/general/infoinhibitor summary: Info-level alert inhibition. expr: ALERTS{severity = "info"} == 1 unless on(namespace) ALERTS{alertname != "InfoInhibitor", severity =~ "warning|critical", alertstate="firing"} == 1 labels: severity: none - name: node-network rules: - alert: NodeNetworkInterfaceFlapping annotations: description: Network interface "{{ $labels.device }}" changing its up status often on node-exporter {{ $labels.namespace }}/{{ $labels.pod }} runbook_url: https://runbooks.prometheus-operator.dev/runbooks/general/nodenetworkinterfaceflapping summary: Network interface is often changing its status expr: | changes(node_network_up{job="node-exporter",device!~"veth.+"}[2m]) > 2 for: 2m labels: severity: warning - name: kube-prometheus-node-recording.rules rules: - expr: sum(rate(node_cpu_seconds_total{mode!="idle",mode!="iowait",mode!="steal"}[3m])) BY (instance) record: instance:node_cpu:rate:sum - expr: sum(rate(node_network_receive_bytes_total[3m])) BY (instance) record: instance:node_network_receive_bytes:rate:sum - expr: sum(rate(node_network_transmit_bytes_total[3m])) BY (instance) record: instance:node_network_transmit_bytes:rate:sum - expr: sum(rate(node_cpu_seconds_total{mode!="idle",mode!="iowait",mode!="steal"}[5m])) WITHOUT (cpu, mode) / ON(instance) GROUP_LEFT() count(sum(node_cpu_seconds_total) BY (instance, cpu)) BY (instance) record: instance:node_cpu:ratio - expr: sum(rate(node_cpu_seconds_total{mode!="idle",mode!="iowait",mode!="steal"}[5m])) record: cluster:node_cpu:sum_rate5m - expr: cluster:node_cpu:sum_rate5m / count(sum(node_cpu_seconds_total) BY (instance, cpu)) record: cluster:node_cpu:ratio - name: kube-prometheus-general.rules rules: - expr: count without(instance, pod, node) (up == 1) record: count:up1 - expr: count without(instance, pod, node) (up == 0) record: count:up0 ================================================ FILE: hack/config/monitoring/kube-prometheus/kubeStateMetrics-clusterRole.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 2.16.0 name: kube-state-metrics rules: - apiGroups: - "" resources: - configmaps - secrets - nodes - pods - services - serviceaccounts - resourcequotas - replicationcontrollers - limitranges - persistentvolumeclaims - persistentvolumes - namespaces - endpoints verbs: - list - watch - apiGroups: - apps resources: - statefulsets - daemonsets - deployments - replicasets verbs: - list - watch - apiGroups: - batch resources: - cronjobs - jobs verbs: - list - watch - apiGroups: - autoscaling resources: - horizontalpodautoscalers verbs: - list - watch - apiGroups: - authentication.k8s.io resources: - tokenreviews verbs: - create - apiGroups: - authorization.k8s.io resources: - subjectaccessreviews verbs: - create - apiGroups: - policy resources: - poddisruptionbudgets verbs: - list - watch - apiGroups: - certificates.k8s.io resources: - certificatesigningrequests verbs: - list - watch - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch - apiGroups: - storage.k8s.io resources: - storageclasses - volumeattachments verbs: - list - watch - apiGroups: - admissionregistration.k8s.io resources: - mutatingwebhookconfigurations - validatingwebhookconfigurations verbs: - list - watch - apiGroups: - networking.k8s.io resources: - networkpolicies - ingressclasses - ingresses verbs: - list - watch - apiGroups: - coordination.k8s.io resources: - leases verbs: - list - watch - apiGroups: - rbac.authorization.k8s.io resources: - clusterrolebindings - clusterroles - rolebindings - roles verbs: - list - watch ================================================ FILE: hack/config/monitoring/kube-prometheus/kubeStateMetrics-clusterRoleBinding.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 2.16.0 name: kube-state-metrics roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: kube-state-metrics subjects: - kind: ServiceAccount name: kube-state-metrics namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/kubeStateMetrics-deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 2.16.0 name: kube-state-metrics namespace: monitoring spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/part-of: kube-prometheus template: metadata: annotations: kubectl.kubernetes.io/default-container: kube-state-metrics labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 2.16.0 spec: automountServiceAccountToken: true containers: - args: - --host=127.0.0.1 - --port=8081 - --telemetry-host=127.0.0.1 - --telemetry-port=8082 image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.16.0 name: kube-state-metrics resources: limits: cpu: 100m memory: 250Mi requests: cpu: 10m memory: 190Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65534 runAsNonRoot: true runAsUser: 65534 seccompProfile: type: RuntimeDefault - args: - --secure-listen-address=:8443 - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 - --upstream=http://127.0.0.1:8081/ image: quay.io/brancz/kube-rbac-proxy:v0.19.1 name: kube-rbac-proxy-main ports: - containerPort: 8443 name: https-main resources: limits: cpu: 40m memory: 40Mi requests: cpu: 20m memory: 20Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65532 runAsNonRoot: true runAsUser: 65532 seccompProfile: type: RuntimeDefault - args: - --secure-listen-address=:9443 - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 - --upstream=http://127.0.0.1:8082/ image: quay.io/brancz/kube-rbac-proxy:v0.19.1 name: kube-rbac-proxy-self ports: - containerPort: 9443 name: https-self resources: limits: cpu: 20m memory: 40Mi requests: cpu: 10m memory: 20Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65532 runAsNonRoot: true runAsUser: 65532 seccompProfile: type: RuntimeDefault nodeSelector: kubernetes.io/os: linux serviceAccountName: kube-state-metrics ================================================ FILE: hack/config/monitoring/kube-prometheus/kubeStateMetrics-networkPolicy.yaml ================================================ apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 2.16.0 name: kube-state-metrics namespace: monitoring spec: egress: - {} ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: prometheus ports: - port: 8443 protocol: TCP - port: 9443 protocol: TCP podSelector: matchLabels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/part-of: kube-prometheus policyTypes: - Egress - Ingress ================================================ FILE: hack/config/monitoring/kube-prometheus/kubeStateMetrics-prometheusRule.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 2.16.0 prometheus: k8s role: alert-rules name: kube-state-metrics-rules namespace: monitoring spec: groups: - name: kube-state-metrics rules: - alert: KubeStateMetricsListErrors annotations: description: kube-state-metrics is experiencing errors at an elevated rate in list operations. This is likely causing it to not be able to expose metrics about Kubernetes objects correctly or at all. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kube-state-metrics/kubestatemetricslisterrors summary: kube-state-metrics is experiencing errors in list operations. expr: | (sum(rate(kube_state_metrics_list_total{job="kube-state-metrics",result="error"}[5m])) by (cluster) / sum(rate(kube_state_metrics_list_total{job="kube-state-metrics"}[5m])) by (cluster)) > 0.01 for: 15m labels: severity: critical - alert: KubeStateMetricsWatchErrors annotations: description: kube-state-metrics is experiencing errors at an elevated rate in watch operations. This is likely causing it to not be able to expose metrics about Kubernetes objects correctly or at all. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kube-state-metrics/kubestatemetricswatcherrors summary: kube-state-metrics is experiencing errors in watch operations. expr: | (sum(rate(kube_state_metrics_watch_total{job="kube-state-metrics",result="error"}[5m])) by (cluster) / sum(rate(kube_state_metrics_watch_total{job="kube-state-metrics"}[5m])) by (cluster)) > 0.01 for: 15m labels: severity: critical - alert: KubeStateMetricsShardingMismatch annotations: description: kube-state-metrics pods are running with different --total-shards configuration, some Kubernetes objects may be exposed multiple times or not exposed at all. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kube-state-metrics/kubestatemetricsshardingmismatch summary: kube-state-metrics sharding is misconfigured. expr: | stdvar (kube_state_metrics_total_shards{job="kube-state-metrics"}) by (cluster) != 0 for: 15m labels: severity: critical - alert: KubeStateMetricsShardsMissing annotations: description: kube-state-metrics shards are missing, some Kubernetes objects are not being exposed. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kube-state-metrics/kubestatemetricsshardsmissing summary: kube-state-metrics shards are missing. expr: | 2^max(kube_state_metrics_total_shards{job="kube-state-metrics"}) by (cluster) - 1 - sum( 2 ^ max by (cluster, shard_ordinal) (kube_state_metrics_shard_ordinal{job="kube-state-metrics"}) ) by (cluster) != 0 for: 15m labels: severity: critical ================================================ FILE: hack/config/monitoring/kube-prometheus/kubeStateMetrics-service.yaml ================================================ apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 2.16.0 name: kube-state-metrics namespace: monitoring spec: clusterIP: None ports: - name: https-main port: 8443 targetPort: https-main - name: https-self port: 9443 targetPort: https-self selector: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/part-of: kube-prometheus ================================================ FILE: hack/config/monitoring/kube-prometheus/kubeStateMetrics-serviceAccount.yaml ================================================ apiVersion: v1 automountServiceAccountToken: false kind: ServiceAccount metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 2.16.0 name: kube-state-metrics namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/kubeStateMetrics-serviceMonitor.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 2.16.0 name: kube-state-metrics namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token honorLabels: true interval: 30s metricRelabelings: - action: drop regex: kube_(endpoint_(address_not_ready|address_available|ports)) sourceLabels: - __name__ port: https-main relabelings: - action: labeldrop regex: (pod|service|endpoint|namespace) scheme: https scrapeTimeout: 30s tlsConfig: insecureSkipVerify: true - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 30s port: https-self scheme: https tlsConfig: insecureSkipVerify: true jobLabel: app.kubernetes.io/name selector: matchLabels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/part-of: kube-prometheus ================================================ FILE: hack/config/monitoring/kube-prometheus/kubernetesControlPlane-prometheusRule.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: labels: app.kubernetes.io/component: kubernetes app.kubernetes.io/name: kube-prometheus app.kubernetes.io/part-of: kube-prometheus prometheus: k8s role: alert-rules name: kubernetes-monitoring-rules namespace: monitoring spec: groups: - name: kubernetes-apps rules: - alert: KubePodCrashLooping annotations: description: 'Pod {{ $labels.namespace }}/{{ $labels.pod }} ({{ $labels.container }}) is in waiting state (reason: "CrashLoopBackOff") on cluster {{ $labels.cluster }}.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubepodcrashlooping summary: Pod is crash looping. expr: | max_over_time(kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff", job="kube-state-metrics"}[5m]) >= 1 for: 15m labels: severity: warning - alert: KubePodNotReady annotations: description: Pod {{ $labels.namespace }}/{{ $labels.pod }} has been in a non-ready state for longer than 15 minutes on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubepodnotready summary: Pod has been in a non-ready state for more than 15 minutes. expr: | sum by (namespace, pod, cluster) ( max by(namespace, pod, cluster) ( kube_pod_status_phase{job="kube-state-metrics", phase=~"Pending|Unknown|Failed"} ) * on(namespace, pod, cluster) group_left(owner_kind) topk by(namespace, pod, cluster) ( 1, max by(namespace, pod, owner_kind, cluster) (kube_pod_owner{owner_kind!="Job"}) ) ) > 0 for: 15m labels: severity: warning - alert: KubeDeploymentGenerationMismatch annotations: description: Deployment generation for {{ $labels.namespace }}/{{ $labels.deployment }} does not match, this indicates that the Deployment has failed but has not been rolled back on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubedeploymentgenerationmismatch summary: Deployment generation mismatch due to possible roll-back expr: | kube_deployment_status_observed_generation{job="kube-state-metrics"} != kube_deployment_metadata_generation{job="kube-state-metrics"} for: 15m labels: severity: warning - alert: KubeDeploymentReplicasMismatch annotations: description: Deployment {{ $labels.namespace }}/{{ $labels.deployment }} has not matched the expected number of replicas for longer than 15 minutes on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubedeploymentreplicasmismatch summary: Deployment has not matched the expected number of replicas. expr: | ( kube_deployment_spec_replicas{job="kube-state-metrics"} > kube_deployment_status_replicas_available{job="kube-state-metrics"} ) and ( changes(kube_deployment_status_replicas_updated{job="kube-state-metrics"}[10m]) == 0 ) for: 15m labels: severity: warning - alert: KubeDeploymentRolloutStuck annotations: description: Rollout of deployment {{ $labels.namespace }}/{{ $labels.deployment }} is not progressing for longer than 15 minutes on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubedeploymentrolloutstuck summary: Deployment rollout is not progressing. expr: | kube_deployment_status_condition{condition="Progressing", status="false",job="kube-state-metrics"} != 0 for: 15m labels: severity: warning - alert: KubeStatefulSetReplicasMismatch annotations: description: StatefulSet {{ $labels.namespace }}/{{ $labels.statefulset }} has not matched the expected number of replicas for longer than 15 minutes on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubestatefulsetreplicasmismatch summary: StatefulSet has not matched the expected number of replicas. expr: | ( kube_statefulset_status_replicas_ready{job="kube-state-metrics"} != kube_statefulset_replicas{job="kube-state-metrics"} ) and ( changes(kube_statefulset_status_replicas_updated{job="kube-state-metrics"}[10m]) == 0 ) for: 15m labels: severity: warning - alert: KubeStatefulSetGenerationMismatch annotations: description: StatefulSet generation for {{ $labels.namespace }}/{{ $labels.statefulset }} does not match, this indicates that the StatefulSet has failed but has not been rolled back on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubestatefulsetgenerationmismatch summary: StatefulSet generation mismatch due to possible roll-back expr: | kube_statefulset_status_observed_generation{job="kube-state-metrics"} != kube_statefulset_metadata_generation{job="kube-state-metrics"} for: 15m labels: severity: warning - alert: KubeStatefulSetUpdateNotRolledOut annotations: description: StatefulSet {{ $labels.namespace }}/{{ $labels.statefulset }} update has not been rolled out on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubestatefulsetupdatenotrolledout summary: StatefulSet update has not been rolled out. expr: | ( max by(namespace, statefulset, job, cluster) ( kube_statefulset_status_current_revision{job="kube-state-metrics"} unless kube_statefulset_status_update_revision{job="kube-state-metrics"} ) * on(namespace, statefulset, job, cluster) ( kube_statefulset_replicas{job="kube-state-metrics"} != kube_statefulset_status_replicas_updated{job="kube-state-metrics"} ) ) and on(namespace, statefulset, job, cluster) ( changes(kube_statefulset_status_replicas_updated{job="kube-state-metrics"}[5m]) == 0 ) for: 15m labels: severity: warning - alert: KubeDaemonSetRolloutStuck annotations: description: DaemonSet {{ $labels.namespace }}/{{ $labels.daemonset }} has not finished or progressed for at least 15m on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubedaemonsetrolloutstuck summary: DaemonSet rollout is stuck. expr: | ( ( kube_daemonset_status_current_number_scheduled{job="kube-state-metrics"} != kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics"} ) or ( kube_daemonset_status_number_misscheduled{job="kube-state-metrics"} != 0 ) or ( kube_daemonset_status_updated_number_scheduled{job="kube-state-metrics"} != kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics"} ) or ( kube_daemonset_status_number_available{job="kube-state-metrics"} != kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics"} ) ) and ( changes(kube_daemonset_status_updated_number_scheduled{job="kube-state-metrics"}[5m]) == 0 ) for: 15m labels: severity: warning - alert: KubeContainerWaiting annotations: description: 'pod/{{ $labels.pod }} in namespace {{ $labels.namespace }} on container {{ $labels.container}} has been in waiting state for longer than 1 hour. (reason: "{{ $labels.reason }}") on cluster {{ $labels.cluster }}.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubecontainerwaiting summary: Pod container waiting longer than 1 hour expr: | kube_pod_container_status_waiting_reason{reason!="CrashLoopBackOff", job="kube-state-metrics"} > 0 for: 1h labels: severity: warning - alert: KubeDaemonSetNotScheduled annotations: description: '{{ $value }} Pods of DaemonSet {{ $labels.namespace }}/{{ $labels.daemonset }} are not scheduled on cluster {{ $labels.cluster }}.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubedaemonsetnotscheduled summary: DaemonSet pods are not scheduled. expr: | kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics"} - kube_daemonset_status_current_number_scheduled{job="kube-state-metrics"} > 0 for: 10m labels: severity: warning - alert: KubeDaemonSetMisScheduled annotations: description: '{{ $value }} Pods of DaemonSet {{ $labels.namespace }}/{{ $labels.daemonset }} are running where they are not supposed to run on cluster {{ $labels.cluster }}.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubedaemonsetmisscheduled summary: DaemonSet pods are misscheduled. expr: | kube_daemonset_status_number_misscheduled{job="kube-state-metrics"} > 0 for: 15m labels: severity: warning - alert: KubeJobNotCompleted annotations: description: Job {{ $labels.namespace }}/{{ $labels.job_name }} is taking more than {{ "43200" | humanizeDuration }} to complete on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubejobnotcompleted summary: Job did not complete in time expr: | time() - max by(namespace, job_name, cluster) (kube_job_status_start_time{job="kube-state-metrics"} and kube_job_status_active{job="kube-state-metrics"} > 0) > 43200 labels: severity: warning - alert: KubeJobFailed annotations: description: Job {{ $labels.namespace }}/{{ $labels.job_name }} failed to complete. Removing failed job after investigation should clear this alert on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubejobfailed summary: Job failed to complete. expr: | kube_job_failed{job="kube-state-metrics"} > 0 for: 15m labels: severity: warning - alert: KubeHpaReplicasMismatch annotations: description: HPA {{ $labels.namespace }}/{{ $labels.horizontalpodautoscaler }} has not matched the desired number of replicas for longer than 15 minutes on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubehpareplicasmismatch summary: HPA has not matched desired number of replicas. expr: | (kube_horizontalpodautoscaler_status_desired_replicas{job="kube-state-metrics"} != kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics"}) and (kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics"} > kube_horizontalpodautoscaler_spec_min_replicas{job="kube-state-metrics"}) and (kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics"} < kube_horizontalpodautoscaler_spec_max_replicas{job="kube-state-metrics"}) and changes(kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics"}[15m]) == 0 for: 15m labels: severity: warning - alert: KubeHpaMaxedOut annotations: description: HPA {{ $labels.namespace }}/{{ $labels.horizontalpodautoscaler }} has been running at max replicas for longer than 15 minutes on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubehpamaxedout summary: HPA is running at max replicas expr: | kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics"} == kube_horizontalpodautoscaler_spec_max_replicas{job="kube-state-metrics"} for: 15m labels: severity: warning - alert: KubePdbNotEnoughHealthyPods annotations: description: PDB {{ $labels.cluster }}/{{ $labels.namespace }}/{{ $labels.poddisruptionbudget }} expects {{ $value }} more healthy pods. The desired number of healthy pods has not been met for at least 15m. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubepdbnotenoughhealthypods summary: PDB does not have enough healthy pods. expr: | ( kube_poddisruptionbudget_status_desired_healthy{job="kube-state-metrics"} - kube_poddisruptionbudget_status_current_healthy{job="kube-state-metrics"} ) > 0 for: 15m labels: severity: warning - name: kubernetes-resources rules: - alert: KubeCPUOvercommit annotations: description: Cluster {{ $labels.cluster }} has overcommitted CPU resource requests for Pods by {{ printf "%.2f" $value }} CPU shares and cannot tolerate node failure. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubecpuovercommit summary: Cluster has overcommitted CPU resource requests. expr: | # Non-HA clusters. ( ( sum by(cluster) (namespace_cpu:kube_pod_container_resource_requests:sum{}) - sum by(cluster) (kube_node_status_allocatable{job="kube-state-metrics",resource="cpu"}) > 0 ) and count by (cluster) (max by (cluster, node) (kube_node_role{job="kube-state-metrics", role="control-plane"})) < 3 ) or # HA clusters. ( sum by(cluster) (namespace_cpu:kube_pod_container_resource_requests:sum{}) - ( # Skip clusters with only one allocatable node. ( sum by (cluster) (kube_node_status_allocatable{job="kube-state-metrics",resource="cpu"}) - max by (cluster) (kube_node_status_allocatable{job="kube-state-metrics",resource="cpu"}) ) > 0 ) > 0 ) for: 10m labels: severity: warning - alert: KubeMemoryOvercommit annotations: description: Cluster {{ $labels.cluster }} has overcommitted memory resource requests for Pods by {{ $value | humanize }} bytes and cannot tolerate node failure. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubememoryovercommit summary: Cluster has overcommitted memory resource requests. expr: | # Non-HA clusters. ( ( sum by(cluster) (namespace_memory:kube_pod_container_resource_requests:sum{}) - sum by(cluster) (kube_node_status_allocatable{job="kube-state-metrics",resource="memory"}) > 0 ) and count by (cluster) (max by (cluster, node) (kube_node_role{job="kube-state-metrics", role="control-plane"})) < 3 ) or # HA clusters. ( sum by(cluster) (namespace_memory:kube_pod_container_resource_requests:sum{}) - ( # Skip clusters with only one allocatable node. ( sum by (cluster) (kube_node_status_allocatable{job="kube-state-metrics",resource="memory"}) - max by (cluster) (kube_node_status_allocatable{job="kube-state-metrics",resource="memory"}) ) > 0 ) > 0 ) for: 10m labels: severity: warning - alert: KubeCPUQuotaOvercommit annotations: description: Cluster {{ $labels.cluster }} has overcommitted CPU resource requests for Namespaces. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubecpuquotaovercommit summary: Cluster has overcommitted CPU resource requests. expr: | sum by(cluster) ( min without(resource) (kube_resourcequota{job="kube-state-metrics", type="hard", resource=~"(cpu|requests.cpu)"}) ) / sum by(cluster) ( kube_node_status_allocatable{resource="cpu", job="kube-state-metrics"} ) > 1.5 for: 5m labels: severity: warning - alert: KubeMemoryQuotaOvercommit annotations: description: Cluster {{ $labels.cluster }} has overcommitted memory resource requests for Namespaces. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubememoryquotaovercommit summary: Cluster has overcommitted memory resource requests. expr: | sum by(cluster) ( min without(resource) (kube_resourcequota{job="kube-state-metrics", type="hard", resource=~"(memory|requests.memory)"}) ) / sum by(cluster) ( kube_node_status_allocatable{resource="memory", job="kube-state-metrics"} ) > 1.5 for: 5m labels: severity: warning - alert: KubeQuotaAlmostFull annotations: description: Namespace {{ $labels.namespace }} is using {{ $value | humanizePercentage }} of its {{ $labels.resource }} quota on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubequotaalmostfull summary: Namespace quota is going to be full. expr: | kube_resourcequota{job="kube-state-metrics", type="used"} / ignoring(instance, job, type) (kube_resourcequota{job="kube-state-metrics", type="hard"} > 0) > 0.9 < 1 for: 15m labels: severity: info - alert: KubeQuotaFullyUsed annotations: description: Namespace {{ $labels.namespace }} is using {{ $value | humanizePercentage }} of its {{ $labels.resource }} quota on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubequotafullyused summary: Namespace quota is fully used. expr: | kube_resourcequota{job="kube-state-metrics", type="used"} / ignoring(instance, job, type) (kube_resourcequota{job="kube-state-metrics", type="hard"} > 0) == 1 for: 15m labels: severity: info - alert: KubeQuotaExceeded annotations: description: Namespace {{ $labels.namespace }} is using {{ $value | humanizePercentage }} of its {{ $labels.resource }} quota on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubequotaexceeded summary: Namespace quota has exceeded the limits. expr: | kube_resourcequota{job="kube-state-metrics", type="used"} / ignoring(instance, job, type) (kube_resourcequota{job="kube-state-metrics", type="hard"} > 0) > 1 for: 15m labels: severity: warning - alert: CPUThrottlingHigh annotations: description: '{{ $value | humanizePercentage }} throttling of CPU in namespace {{ $labels.namespace }} for container {{ $labels.container }} in pod {{ $labels.pod }} on cluster {{ $labels.cluster }}.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/cputhrottlinghigh summary: Processes experience elevated CPU throttling. expr: | sum(increase(container_cpu_cfs_throttled_periods_total{container!="", job="kubelet", metrics_path="/metrics/cadvisor", }[5m])) without (id, metrics_path, name, image, endpoint, job, node) / on (cluster, namespace, pod, container, instance) group_left sum(increase(container_cpu_cfs_periods_total{job="kubelet", metrics_path="/metrics/cadvisor", }[5m])) without (id, metrics_path, name, image, endpoint, job, node) > ( 25 / 100 ) for: 15m labels: severity: info - name: kubernetes-storage rules: - alert: KubePersistentVolumeFillingUp annotations: description: The PersistentVolume claimed by {{ $labels.persistentvolumeclaim }} in Namespace {{ $labels.namespace }} {{ with $labels.cluster -}} on Cluster {{ . }} {{- end }} is only {{ $value | humanizePercentage }} free. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubepersistentvolumefillingup summary: PersistentVolume is filling up. expr: | ( kubelet_volume_stats_available_bytes{job="kubelet", metrics_path="/metrics"} / kubelet_volume_stats_capacity_bytes{job="kubelet", metrics_path="/metrics"} ) < 0.03 and kubelet_volume_stats_used_bytes{job="kubelet", metrics_path="/metrics"} > 0 unless on(cluster, namespace, persistentvolumeclaim) kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 unless on(cluster, namespace, persistentvolumeclaim) kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 for: 1m labels: severity: critical - alert: KubePersistentVolumeFillingUp annotations: description: Based on recent sampling, the PersistentVolume claimed by {{ $labels.persistentvolumeclaim }} in Namespace {{ $labels.namespace }} {{ with $labels.cluster -}} on Cluster {{ . }} {{- end }} is expected to fill up within four days. Currently {{ $value | humanizePercentage }} is available. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubepersistentvolumefillingup summary: PersistentVolume is filling up. expr: | ( kubelet_volume_stats_available_bytes{job="kubelet", metrics_path="/metrics"} / kubelet_volume_stats_capacity_bytes{job="kubelet", metrics_path="/metrics"} ) < 0.15 and kubelet_volume_stats_used_bytes{job="kubelet", metrics_path="/metrics"} > 0 and predict_linear(kubelet_volume_stats_available_bytes{job="kubelet", metrics_path="/metrics"}[6h], 4 * 24 * 3600) < 0 unless on(cluster, namespace, persistentvolumeclaim) kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 unless on(cluster, namespace, persistentvolumeclaim) kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 for: 1h labels: severity: warning - alert: KubePersistentVolumeInodesFillingUp annotations: description: The PersistentVolume claimed by {{ $labels.persistentvolumeclaim }} in Namespace {{ $labels.namespace }} {{ with $labels.cluster -}} on Cluster {{ . }} {{- end }} only has {{ $value | humanizePercentage }} free inodes. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubepersistentvolumeinodesfillingup summary: PersistentVolumeInodes are filling up. expr: | ( kubelet_volume_stats_inodes_free{job="kubelet", metrics_path="/metrics"} / kubelet_volume_stats_inodes{job="kubelet", metrics_path="/metrics"} ) < 0.03 and kubelet_volume_stats_inodes_used{job="kubelet", metrics_path="/metrics"} > 0 unless on(cluster, namespace, persistentvolumeclaim) kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 unless on(cluster, namespace, persistentvolumeclaim) kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 for: 1m labels: severity: critical - alert: KubePersistentVolumeInodesFillingUp annotations: description: Based on recent sampling, the PersistentVolume claimed by {{ $labels.persistentvolumeclaim }} in Namespace {{ $labels.namespace }} {{ with $labels.cluster -}} on Cluster {{ . }} {{- end }} is expected to run out of inodes within four days. Currently {{ $value | humanizePercentage }} of its inodes are free. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubepersistentvolumeinodesfillingup summary: PersistentVolumeInodes are filling up. expr: | ( kubelet_volume_stats_inodes_free{job="kubelet", metrics_path="/metrics"} / kubelet_volume_stats_inodes{job="kubelet", metrics_path="/metrics"} ) < 0.15 and kubelet_volume_stats_inodes_used{job="kubelet", metrics_path="/metrics"} > 0 and predict_linear(kubelet_volume_stats_inodes_free{job="kubelet", metrics_path="/metrics"}[6h], 4 * 24 * 3600) < 0 unless on(cluster, namespace, persistentvolumeclaim) kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 unless on(cluster, namespace, persistentvolumeclaim) kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 for: 1h labels: severity: warning - alert: KubePersistentVolumeErrors annotations: description: The persistent volume {{ $labels.persistentvolume }} {{ with $labels.cluster -}} on Cluster {{ . }} {{- end }} has status {{ $labels.phase }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubepersistentvolumeerrors summary: PersistentVolume is having issues with provisioning. expr: | kube_persistentvolume_status_phase{phase=~"Failed|Pending",job="kube-state-metrics"} > 0 for: 5m labels: severity: critical - name: kubernetes-system rules: - alert: KubeVersionMismatch annotations: description: There are {{ $value }} different semantic versions of Kubernetes components running on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeversionmismatch summary: Different semantic versions of Kubernetes components running. expr: | count by (cluster) (count by (git_version, cluster) (label_replace(kubernetes_build_info{job!~"kube-dns|coredns"},"git_version","$1","git_version","(v[0-9]*.[0-9]*).*"))) > 1 for: 15m labels: severity: warning - alert: KubeClientErrors annotations: description: Kubernetes API server client '{{ $labels.job }}/{{ $labels.instance }}' is experiencing {{ $value | humanizePercentage }} errors on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeclienterrors summary: Kubernetes API server client is experiencing errors. expr: | (sum(rate(rest_client_requests_total{job="apiserver",code=~"5.."}[5m])) by (cluster, instance, job, namespace) / sum(rate(rest_client_requests_total{job="apiserver"}[5m])) by (cluster, instance, job, namespace)) > 0.01 for: 15m labels: severity: warning - name: kube-apiserver-slos rules: - alert: KubeAPIErrorBudgetBurn annotations: description: The API server is burning too much error budget on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeapierrorbudgetburn summary: The API server is burning too much error budget. expr: | sum by(cluster) (apiserver_request:burnrate1h) > (14.40 * 0.01000) and on(cluster) sum by(cluster) (apiserver_request:burnrate5m) > (14.40 * 0.01000) for: 2m labels: long: 1h severity: critical short: 5m - alert: KubeAPIErrorBudgetBurn annotations: description: The API server is burning too much error budget on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeapierrorbudgetburn summary: The API server is burning too much error budget. expr: | sum by(cluster) (apiserver_request:burnrate6h) > (6.00 * 0.01000) and on(cluster) sum by(cluster) (apiserver_request:burnrate30m) > (6.00 * 0.01000) for: 15m labels: long: 6h severity: critical short: 30m - alert: KubeAPIErrorBudgetBurn annotations: description: The API server is burning too much error budget on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeapierrorbudgetburn summary: The API server is burning too much error budget. expr: | sum by(cluster) (apiserver_request:burnrate1d) > (3.00 * 0.01000) and on(cluster) sum by(cluster) (apiserver_request:burnrate2h) > (3.00 * 0.01000) for: 1h labels: long: 1d severity: warning short: 2h - alert: KubeAPIErrorBudgetBurn annotations: description: The API server is burning too much error budget on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeapierrorbudgetburn summary: The API server is burning too much error budget. expr: | sum by(cluster) (apiserver_request:burnrate3d) > (1.00 * 0.01000) and on(cluster) sum by(cluster) (apiserver_request:burnrate6h) > (1.00 * 0.01000) for: 3h labels: long: 3d severity: warning short: 6h - name: kubernetes-system-apiserver rules: - alert: KubeClientCertificateExpiration annotations: description: A client certificate used to authenticate to kubernetes apiserver is expiring in less than 7.0 days on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeclientcertificateexpiration summary: Client certificate is about to expire. expr: | histogram_quantile(0.01, sum without (namespace, service, endpoint) (rate(apiserver_client_certificate_expiration_seconds_bucket{job="apiserver"}[5m]))) < 604800 and on(job, cluster, instance) apiserver_client_certificate_expiration_seconds_count{job="apiserver"} > 0 for: 5m labels: severity: warning - alert: KubeClientCertificateExpiration annotations: description: A client certificate used to authenticate to kubernetes apiserver is expiring in less than 24.0 hours on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeclientcertificateexpiration summary: Client certificate is about to expire. expr: | histogram_quantile(0.01, sum without (namespace, service, endpoint) (rate(apiserver_client_certificate_expiration_seconds_bucket{job="apiserver"}[5m]))) < 86400 and on(job, cluster, instance) apiserver_client_certificate_expiration_seconds_count{job="apiserver"} > 0 for: 5m labels: severity: critical - alert: KubeAggregatedAPIErrors annotations: description: Kubernetes aggregated API {{ $labels.instance }}/{{ $labels.name }} has reported {{ $labels.reason }} errors on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeaggregatedapierrors summary: Kubernetes aggregated API has reported errors. expr: | sum by(cluster, instance, name, reason)(increase(aggregator_unavailable_apiservice_total{job="apiserver"}[1m])) > 0 for: 10m labels: severity: warning - alert: KubeAggregatedAPIDown annotations: description: Kubernetes aggregated API {{ $labels.name }}/{{ $labels.namespace }} has been only {{ $value | humanize }}% available over the last 10m on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeaggregatedapidown summary: Kubernetes aggregated API is down. expr: | (1 - max by(name, namespace, cluster)(avg_over_time(aggregator_unavailable_apiservice{job="apiserver"}[10m]))) * 100 < 85 for: 5m labels: severity: warning - alert: KubeAPIDown annotations: description: KubeAPI has disappeared from Prometheus target discovery. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeapidown summary: Target disappeared from Prometheus target discovery. expr: | absent(up{job="apiserver"} == 1) for: 15m labels: severity: critical - alert: KubeAPITerminatedRequests annotations: description: The kubernetes apiserver has terminated {{ $value | humanizePercentage }} of its incoming requests on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeapiterminatedrequests summary: The kubernetes apiserver has terminated {{ $value | humanizePercentage }} of its incoming requests. expr: | sum by(cluster) (rate(apiserver_request_terminations_total{job="apiserver"}[10m])) / ( sum by(cluster) (rate(apiserver_request_total{job="apiserver"}[10m])) + sum by(cluster) (rate(apiserver_request_terminations_total{job="apiserver"}[10m])) ) > 0.20 for: 5m labels: severity: warning - name: kubernetes-system-kubelet rules: - alert: KubeNodeNotReady annotations: description: '{{ $labels.node }} has been unready for more than 15 minutes on cluster {{ $labels.cluster }}.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubenodenotready summary: Node is not ready. expr: | kube_node_status_condition{job="kube-state-metrics",condition="Ready",status="true"} == 0 and on (cluster, node) kube_node_spec_unschedulable{job="kube-state-metrics"} == 0 for: 15m labels: severity: warning - alert: KubeNodePressure annotations: description: '{{ $labels.node }} on cluster {{ $labels.cluster }} has active Condition {{ $labels.condition }}. This is caused by resource usage exceeding eviction thresholds.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubenodepressure summary: Node has as active Condition. expr: | kube_node_status_condition{job="kube-state-metrics",condition=~"(MemoryPressure|DiskPressure|PIDPressure)",status="true"} == 1 and on (cluster, node) kube_node_spec_unschedulable{job="kube-state-metrics"} == 0 for: 10m labels: severity: info - alert: KubeNodeUnreachable annotations: description: '{{ $labels.node }} is unreachable and some workloads may be rescheduled on cluster {{ $labels.cluster }}.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubenodeunreachable summary: Node is unreachable. expr: | (kube_node_spec_taint{job="kube-state-metrics",key="node.kubernetes.io/unreachable",effect="NoSchedule"} unless ignoring(key,value) kube_node_spec_taint{job="kube-state-metrics",key=~"ToBeDeletedByClusterAutoscaler|cloud.google.com/impending-node-termination|aws-node-termination-handler/spot-itn"}) == 1 for: 15m labels: severity: warning - alert: KubeletTooManyPods annotations: description: Kubelet '{{ $labels.node }}' is running at {{ $value | humanizePercentage }} of its Pod capacity on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubelettoomanypods summary: Kubelet is running at capacity. expr: | ( max by (cluster, instance) ( kubelet_running_pods{job="kubelet", metrics_path="/metrics"} > 1 ) * on (cluster, instance) group_left(node) max by (cluster, instance, node) ( kubelet_node_name{job="kubelet", metrics_path="/metrics"} ) ) / on (cluster, node) group_left() max by (cluster, node) ( kube_node_status_capacity{job="kube-state-metrics", resource="pods"} != 1 ) > 0.95 for: 15m labels: severity: info - alert: KubeNodeReadinessFlapping annotations: description: The readiness status of node {{ $labels.node }} has changed {{ $value }} times in the last 15 minutes on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubenodereadinessflapping summary: Node readiness status is flapping. expr: | sum(changes(kube_node_status_condition{job="kube-state-metrics",status="true",condition="Ready"}[15m])) by (cluster, node) > 2 and on (cluster, node) kube_node_spec_unschedulable{job="kube-state-metrics"} == 0 for: 15m labels: severity: warning - alert: KubeNodeEviction annotations: description: Node {{ $labels.node }} on {{ $labels.cluster }} is evicting Pods due to {{ $labels.eviction_signal }}. Eviction occurs when eviction thresholds are crossed, typically caused by Pods exceeding RAM/ephemeral-storage limits. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubenodeeviction summary: Node is evicting pods. expr: | sum(rate(kubelet_evictions{job="kubelet", metrics_path="/metrics"}[15m])) by(cluster, eviction_signal, instance) * on (cluster, instance) group_left(node) max by (cluster, instance, node) ( kubelet_node_name{job="kubelet", metrics_path="/metrics"} ) > 0 for: 0s labels: severity: info - alert: KubeletPlegDurationHigh annotations: description: The Kubelet Pod Lifecycle Event Generator has a 99th percentile duration of {{ $value }} seconds on node {{ $labels.node }} on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeletplegdurationhigh summary: Kubelet Pod Lifecycle Event Generator is taking too long to relist. expr: | node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile{quantile="0.99"} >= 10 for: 5m labels: severity: warning - alert: KubeletPodStartUpLatencyHigh annotations: description: Kubelet Pod startup 99th percentile latency is {{ $value }} seconds on node {{ $labels.node }} on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeletpodstartuplatencyhigh summary: Kubelet Pod startup latency is too high. expr: | histogram_quantile(0.99, sum by (cluster, instance, le) ( topk by (cluster, instance, le, operation_type) (1, rate(kubelet_pod_worker_duration_seconds_bucket{job="kubelet", metrics_path="/metrics"}[5m]) ) ) ) * on(cluster, instance) group_left(node) topk by (cluster, instance, node) (1, kubelet_node_name{job="kubelet", metrics_path="/metrics"} ) > 60 for: 15m labels: severity: warning - alert: KubeletClientCertificateExpiration annotations: description: Client certificate for Kubelet on node {{ $labels.node }} expires in {{ $value | humanizeDuration }} on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeletclientcertificateexpiration summary: Kubelet client certificate is about to expire. expr: | kubelet_certificate_manager_client_ttl_seconds < 604800 labels: severity: warning - alert: KubeletClientCertificateExpiration annotations: description: Client certificate for Kubelet on node {{ $labels.node }} expires in {{ $value | humanizeDuration }} on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeletclientcertificateexpiration summary: Kubelet client certificate is about to expire. expr: | kubelet_certificate_manager_client_ttl_seconds < 86400 labels: severity: critical - alert: KubeletServerCertificateExpiration annotations: description: Server certificate for Kubelet on node {{ $labels.node }} expires in {{ $value | humanizeDuration }} on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeletservercertificateexpiration summary: Kubelet server certificate is about to expire. expr: | kubelet_certificate_manager_server_ttl_seconds < 604800 labels: severity: warning - alert: KubeletServerCertificateExpiration annotations: description: Server certificate for Kubelet on node {{ $labels.node }} expires in {{ $value | humanizeDuration }} on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeletservercertificateexpiration summary: Kubelet server certificate is about to expire. expr: | kubelet_certificate_manager_server_ttl_seconds < 86400 labels: severity: critical - alert: KubeletClientCertificateRenewalErrors annotations: description: Kubelet on node {{ $labels.node }} has failed to renew its client certificate ({{ $value | humanize }} errors in the last 5 minutes) on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeletclientcertificaterenewalerrors summary: Kubelet has failed to renew its client certificate. expr: | increase(kubelet_certificate_manager_client_expiration_renew_errors[5m]) > 0 for: 15m labels: severity: warning - alert: KubeletServerCertificateRenewalErrors annotations: description: Kubelet on node {{ $labels.node }} has failed to renew its server certificate ({{ $value | humanize }} errors in the last 5 minutes) on cluster {{ $labels.cluster }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeletservercertificaterenewalerrors summary: Kubelet has failed to renew its server certificate. expr: | increase(kubelet_server_expiration_renew_errors[5m]) > 0 for: 15m labels: severity: warning - alert: KubeletDown annotations: description: Kubelet has disappeared from Prometheus target discovery. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeletdown summary: Target disappeared from Prometheus target discovery. expr: | absent(up{job="kubelet", metrics_path="/metrics"} == 1) for: 15m labels: severity: critical - name: kubernetes-system-scheduler rules: - alert: KubeSchedulerDown annotations: description: KubeScheduler has disappeared from Prometheus target discovery. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubeschedulerdown summary: Target disappeared from Prometheus target discovery. expr: | absent(up{job="kube-scheduler"} == 1) for: 15m labels: severity: critical - name: kubernetes-system-controller-manager rules: - alert: KubeControllerManagerDown annotations: description: KubeControllerManager has disappeared from Prometheus target discovery. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/kubernetes/kubecontrollermanagerdown summary: Target disappeared from Prometheus target discovery. expr: | absent(up{job="kube-controller-manager"} == 1) for: 15m labels: severity: critical - interval: 3m name: kube-apiserver-availability.rules rules: - expr: | avg_over_time(code_verb:apiserver_request_total:increase1h[30d]) * 24 * 30 record: code_verb:apiserver_request_total:increase30d - expr: | sum by (cluster, code) (code_verb:apiserver_request_total:increase30d{verb=~"LIST|GET"}) labels: verb: read record: code:apiserver_request_total:increase30d - expr: | sum by (cluster, code) (code_verb:apiserver_request_total:increase30d{verb=~"POST|PUT|PATCH|DELETE"}) labels: verb: write record: code:apiserver_request_total:increase30d - expr: | sum by (cluster, verb, scope, le) (increase(apiserver_request_sli_duration_seconds_bucket[1h])) record: cluster_verb_scope_le:apiserver_request_sli_duration_seconds_bucket:increase1h - expr: | sum by (cluster, verb, scope, le) (avg_over_time(cluster_verb_scope_le:apiserver_request_sli_duration_seconds_bucket:increase1h[30d]) * 24 * 30) record: cluster_verb_scope_le:apiserver_request_sli_duration_seconds_bucket:increase30d - expr: | sum by (cluster, verb, scope) (cluster_verb_scope_le:apiserver_request_sli_duration_seconds_bucket:increase1h{le="+Inf"}) record: cluster_verb_scope:apiserver_request_sli_duration_seconds_count:increase1h - expr: | sum by (cluster, verb, scope) (cluster_verb_scope_le:apiserver_request_sli_duration_seconds_bucket:increase30d{le="+Inf"}) record: cluster_verb_scope:apiserver_request_sli_duration_seconds_count:increase30d - expr: | 1 - ( ( # write too slow sum by (cluster) (cluster_verb_scope:apiserver_request_sli_duration_seconds_count:increase30d{verb=~"POST|PUT|PATCH|DELETE"}) - sum by (cluster) (cluster_verb_scope_le:apiserver_request_sli_duration_seconds_bucket:increase30d{verb=~"POST|PUT|PATCH|DELETE",le=~"1(\\.0)?"} or vector(0)) ) + ( # read too slow sum by (cluster) (cluster_verb_scope:apiserver_request_sli_duration_seconds_count:increase30d{verb=~"LIST|GET"}) - ( sum by (cluster) (cluster_verb_scope_le:apiserver_request_sli_duration_seconds_bucket:increase30d{verb=~"LIST|GET",scope=~"resource|",le=~"1(\\.0)?"} or vector(0)) + sum by (cluster) (cluster_verb_scope_le:apiserver_request_sli_duration_seconds_bucket:increase30d{verb=~"LIST|GET",scope="namespace",le=~"5(\\.0)?"} or vector(0)) + sum by (cluster) (cluster_verb_scope_le:apiserver_request_sli_duration_seconds_bucket:increase30d{verb=~"LIST|GET",scope="cluster",le=~"30(\\.0)?"} or vector(0)) ) ) + # errors sum by (cluster) (code:apiserver_request_total:increase30d{code=~"5.."} or vector(0)) ) / sum by (cluster) (code:apiserver_request_total:increase30d) labels: verb: all record: apiserver_request:availability30d - expr: | 1 - ( sum by (cluster) (cluster_verb_scope:apiserver_request_sli_duration_seconds_count:increase30d{verb=~"LIST|GET"}) - ( # too slow sum by (cluster) (cluster_verb_scope_le:apiserver_request_sli_duration_seconds_bucket:increase30d{verb=~"LIST|GET",scope=~"resource|",le=~"1(\\.0)?"} or vector(0)) + sum by (cluster) (cluster_verb_scope_le:apiserver_request_sli_duration_seconds_bucket:increase30d{verb=~"LIST|GET",scope="namespace",le=~"5(\\.0)?"} or vector(0)) + sum by (cluster) (cluster_verb_scope_le:apiserver_request_sli_duration_seconds_bucket:increase30d{verb=~"LIST|GET",scope="cluster",le=~"30(\\.0)?"} or vector(0)) ) + # errors sum by (cluster) (code:apiserver_request_total:increase30d{verb="read",code=~"5.."} or vector(0)) ) / sum by (cluster) (code:apiserver_request_total:increase30d{verb="read"}) labels: verb: read record: apiserver_request:availability30d - expr: | 1 - ( ( # too slow sum by (cluster) (cluster_verb_scope:apiserver_request_sli_duration_seconds_count:increase30d{verb=~"POST|PUT|PATCH|DELETE"}) - sum by (cluster) (cluster_verb_scope_le:apiserver_request_sli_duration_seconds_bucket:increase30d{verb=~"POST|PUT|PATCH|DELETE",le=~"1(\\.0)?"} or vector(0)) ) + # errors sum by (cluster) (code:apiserver_request_total:increase30d{verb="write",code=~"5.."} or vector(0)) ) / sum by (cluster) (code:apiserver_request_total:increase30d{verb="write"}) labels: verb: write record: apiserver_request:availability30d - expr: | sum by (cluster,code,resource) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[5m])) labels: verb: read record: code_resource:apiserver_request_total:rate5m - expr: | sum by (cluster,code,resource) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[5m])) labels: verb: write record: code_resource:apiserver_request_total:rate5m - expr: | sum by (cluster, code, verb) (increase(apiserver_request_total{job="apiserver",verb=~"LIST|GET|POST|PUT|PATCH|DELETE",code=~"2.."}[1h])) record: code_verb:apiserver_request_total:increase1h - expr: | sum by (cluster, code, verb) (increase(apiserver_request_total{job="apiserver",verb=~"LIST|GET|POST|PUT|PATCH|DELETE",code=~"3.."}[1h])) record: code_verb:apiserver_request_total:increase1h - expr: | sum by (cluster, code, verb) (increase(apiserver_request_total{job="apiserver",verb=~"LIST|GET|POST|PUT|PATCH|DELETE",code=~"4.."}[1h])) record: code_verb:apiserver_request_total:increase1h - expr: | sum by (cluster, code, verb) (increase(apiserver_request_total{job="apiserver",verb=~"LIST|GET|POST|PUT|PATCH|DELETE",code=~"5.."}[1h])) record: code_verb:apiserver_request_total:increase1h - name: kube-apiserver-burnrate.rules rules: - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward"}[1d])) - ( ( sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope=~"resource|",le=~"1(\\.0)?"}[1d])) or vector(0) ) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="namespace",le=~"5(\\.0)?"}[1d])) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="cluster",le=~"30(\\.0)?"}[1d])) ) ) + # errors sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[1d])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[1d])) labels: verb: read record: apiserver_request:burnrate1d - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward"}[1h])) - ( ( sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope=~"resource|",le=~"1(\\.0)?"}[1h])) or vector(0) ) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="namespace",le=~"5(\\.0)?"}[1h])) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="cluster",le=~"30(\\.0)?"}[1h])) ) ) + # errors sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[1h])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[1h])) labels: verb: read record: apiserver_request:burnrate1h - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward"}[2h])) - ( ( sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope=~"resource|",le=~"1(\\.0)?"}[2h])) or vector(0) ) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="namespace",le=~"5(\\.0)?"}[2h])) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="cluster",le=~"30(\\.0)?"}[2h])) ) ) + # errors sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[2h])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[2h])) labels: verb: read record: apiserver_request:burnrate2h - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward"}[30m])) - ( ( sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope=~"resource|",le=~"1(\\.0)?"}[30m])) or vector(0) ) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="namespace",le=~"5(\\.0)?"}[30m])) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="cluster",le=~"30(\\.0)?"}[30m])) ) ) + # errors sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[30m])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[30m])) labels: verb: read record: apiserver_request:burnrate30m - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward"}[3d])) - ( ( sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope=~"resource|",le=~"1(\\.0)?"}[3d])) or vector(0) ) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="namespace",le=~"5(\\.0)?"}[3d])) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="cluster",le=~"30(\\.0)?"}[3d])) ) ) + # errors sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[3d])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[3d])) labels: verb: read record: apiserver_request:burnrate3d - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward"}[5m])) - ( ( sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope=~"resource|",le=~"1(\\.0)?"}[5m])) or vector(0) ) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="namespace",le=~"5(\\.0)?"}[5m])) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="cluster",le=~"30(\\.0)?"}[5m])) ) ) + # errors sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[5m])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[5m])) labels: verb: read record: apiserver_request:burnrate5m - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward"}[6h])) - ( ( sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope=~"resource|",le=~"1(\\.0)?"}[6h])) or vector(0) ) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="namespace",le=~"5(\\.0)?"}[6h])) + sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward",scope="cluster",le=~"30(\\.0)?"}[6h])) ) ) + # errors sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[6h])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[6h])) labels: verb: read record: apiserver_request:burnrate6h - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward"}[1d])) - sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward",le=~"1(\\.0)?"}[1d])) ) + sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[1d])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[1d])) labels: verb: write record: apiserver_request:burnrate1d - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward"}[1h])) - sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward",le=~"1(\\.0)?"}[1h])) ) + sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[1h])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[1h])) labels: verb: write record: apiserver_request:burnrate1h - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward"}[2h])) - sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward",le=~"1(\\.0)?"}[2h])) ) + sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[2h])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[2h])) labels: verb: write record: apiserver_request:burnrate2h - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward"}[30m])) - sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward",le=~"1(\\.0)?"}[30m])) ) + sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[30m])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[30m])) labels: verb: write record: apiserver_request:burnrate30m - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward"}[3d])) - sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward",le=~"1(\\.0)?"}[3d])) ) + sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[3d])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[3d])) labels: verb: write record: apiserver_request:burnrate3d - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward"}[5m])) - sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward",le=~"1(\\.0)?"}[5m])) ) + sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[5m])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[5m])) labels: verb: write record: apiserver_request:burnrate5m - expr: | ( ( # too slow sum by (cluster) (rate(apiserver_request_sli_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward"}[6h])) - sum by (cluster) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward",le=~"1(\\.0)?"}[6h])) ) + sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[6h])) ) / sum by (cluster) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[6h])) labels: verb: write record: apiserver_request:burnrate6h - name: kube-apiserver-histogram.rules rules: - expr: | histogram_quantile(0.99, sum by (cluster, le, resource) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",subresource!~"proxy|attach|log|exec|portforward"}[5m]))) > 0 labels: quantile: "0.99" verb: read record: cluster_quantile:apiserver_request_sli_duration_seconds:histogram_quantile - expr: | histogram_quantile(0.99, sum by (cluster, le, resource) (rate(apiserver_request_sli_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",subresource!~"proxy|attach|log|exec|portforward"}[5m]))) > 0 labels: quantile: "0.99" verb: write record: cluster_quantile:apiserver_request_sli_duration_seconds:histogram_quantile - name: k8s.rules.container_cpu_usage_seconds_total rules: - expr: | sum by (cluster, namespace, pod, container) ( rate(container_cpu_usage_seconds_total{job="kubelet", metrics_path="/metrics/cadvisor", image!=""}[5m]) ) * on (cluster, namespace, pod) group_left(node) topk by (cluster, namespace, pod) ( 1, max by(cluster, namespace, pod, node) (kube_pod_info{node!=""}) ) record: node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate5m - expr: | sum by (cluster, namespace, pod, container) ( irate(container_cpu_usage_seconds_total{job="kubelet", metrics_path="/metrics/cadvisor", image!=""}[5m]) ) * on (cluster, namespace, pod) group_left(node) topk by (cluster, namespace, pod) ( 1, max by(cluster, namespace, pod, node) (kube_pod_info{node!=""}) ) record: node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate - name: k8s.rules.container_memory_working_set_bytes rules: - expr: | container_memory_working_set_bytes{job="kubelet", metrics_path="/metrics/cadvisor", image!=""} * on (cluster, namespace, pod) group_left(node) topk by(cluster, namespace, pod) (1, max by(cluster, namespace, pod, node) (kube_pod_info{node!=""}) ) record: node_namespace_pod_container:container_memory_working_set_bytes - name: k8s.rules.container_memory_rss rules: - expr: | container_memory_rss{job="kubelet", metrics_path="/metrics/cadvisor", image!=""} * on (cluster, namespace, pod) group_left(node) topk by(cluster, namespace, pod) (1, max by(cluster, namespace, pod, node) (kube_pod_info{node!=""}) ) record: node_namespace_pod_container:container_memory_rss - name: k8s.rules.container_memory_cache rules: - expr: | container_memory_cache{job="kubelet", metrics_path="/metrics/cadvisor", image!=""} * on (cluster, namespace, pod) group_left(node) topk by(cluster, namespace, pod) (1, max by(cluster, namespace, pod, node) (kube_pod_info{node!=""}) ) record: node_namespace_pod_container:container_memory_cache - name: k8s.rules.container_memory_swap rules: - expr: | container_memory_swap{job="kubelet", metrics_path="/metrics/cadvisor", image!=""} * on (cluster, namespace, pod) group_left(node) topk by(cluster, namespace, pod) (1, max by(cluster, namespace, pod, node) (kube_pod_info{node!=""}) ) record: node_namespace_pod_container:container_memory_swap - name: k8s.rules.container_memory_requests rules: - expr: | kube_pod_container_resource_requests{resource="memory",job="kube-state-metrics"} * on (namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( (kube_pod_status_phase{phase=~"Pending|Running"} == 1) ) record: cluster:namespace:pod_memory:active:kube_pod_container_resource_requests - expr: | sum by (namespace, cluster) ( sum by (namespace, pod, cluster) ( max by (namespace, pod, container, cluster) ( kube_pod_container_resource_requests{resource="memory",job="kube-state-metrics"} ) * on(namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( kube_pod_status_phase{phase=~"Pending|Running"} == 1 ) ) ) record: namespace_memory:kube_pod_container_resource_requests:sum - name: k8s.rules.container_cpu_requests rules: - expr: | kube_pod_container_resource_requests{resource="cpu",job="kube-state-metrics"} * on (namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( (kube_pod_status_phase{phase=~"Pending|Running"} == 1) ) record: cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests - expr: | sum by (namespace, cluster) ( sum by (namespace, pod, cluster) ( max by (namespace, pod, container, cluster) ( kube_pod_container_resource_requests{resource="cpu",job="kube-state-metrics"} ) * on(namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( kube_pod_status_phase{phase=~"Pending|Running"} == 1 ) ) ) record: namespace_cpu:kube_pod_container_resource_requests:sum - name: k8s.rules.container_memory_limits rules: - expr: | kube_pod_container_resource_limits{resource="memory",job="kube-state-metrics"} * on (namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( (kube_pod_status_phase{phase=~"Pending|Running"} == 1) ) record: cluster:namespace:pod_memory:active:kube_pod_container_resource_limits - expr: | sum by (namespace, cluster) ( sum by (namespace, pod, cluster) ( max by (namespace, pod, container, cluster) ( kube_pod_container_resource_limits{resource="memory",job="kube-state-metrics"} ) * on(namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( kube_pod_status_phase{phase=~"Pending|Running"} == 1 ) ) ) record: namespace_memory:kube_pod_container_resource_limits:sum - name: k8s.rules.container_cpu_limits rules: - expr: | kube_pod_container_resource_limits{resource="cpu",job="kube-state-metrics"} * on (namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( (kube_pod_status_phase{phase=~"Pending|Running"} == 1) ) record: cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits - expr: | sum by (namespace, cluster) ( sum by (namespace, pod, cluster) ( max by (namespace, pod, container, cluster) ( kube_pod_container_resource_limits{resource="cpu",job="kube-state-metrics"} ) * on(namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( kube_pod_status_phase{phase=~"Pending|Running"} == 1 ) ) ) record: namespace_cpu:kube_pod_container_resource_limits:sum - name: k8s.rules.pod_owner rules: - expr: | max by (cluster, namespace, workload, pod) ( label_replace( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="ReplicaSet"}, "replicaset", "$1", "owner_name", "(.*)" ) * on (cluster, replicaset, namespace) group_left(owner_name) topk by(cluster, replicaset, namespace) ( 1, max by (cluster, replicaset, namespace, owner_name) ( kube_replicaset_owner{job="kube-state-metrics", owner_kind=""} ) ), "workload", "$1", "replicaset", "(.*)" ) ) labels: workload_type: replicaset record: namespace_workload_pod:kube_pod_owner:relabel - expr: | max by (cluster, namespace, workload, pod) ( label_replace( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="ReplicaSet"}, "replicaset", "$1", "owner_name", "(.*)" ) * on(replicaset, namespace, cluster) group_left(owner_name) topk by(cluster, replicaset, namespace) ( 1, max by (cluster, replicaset, namespace, owner_name) ( kube_replicaset_owner{job="kube-state-metrics", owner_kind="Deployment"} ) ), "workload", "$1", "owner_name", "(.*)" ) ) labels: workload_type: deployment record: namespace_workload_pod:kube_pod_owner:relabel - expr: | max by (cluster, namespace, workload, pod) ( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="DaemonSet"}, "workload", "$1", "owner_name", "(.*)" ) ) labels: workload_type: daemonset record: namespace_workload_pod:kube_pod_owner:relabel - expr: | max by (cluster, namespace, workload, pod) ( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="StatefulSet"}, "workload", "$1", "owner_name", "(.*)") ) labels: workload_type: statefulset record: namespace_workload_pod:kube_pod_owner:relabel - expr: | group by (cluster, namespace, workload, pod) ( label_join( group by (cluster, namespace, job_name, pod, owner_name) ( label_join( kube_pod_owner{job="kube-state-metrics", owner_kind="Job"} , "job_name", "", "owner_name") ) * on (cluster, namespace, job_name) group_left() group by (cluster, namespace, job_name) ( kube_job_owner{job="kube-state-metrics", owner_kind=~"Pod|"} ) , "workload", "", "owner_name") ) labels: workload_type: job record: namespace_workload_pod:kube_pod_owner:relabel - expr: | max by (cluster, namespace, workload, pod) ( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="", owner_name=""}, "workload", "$1", "pod", "(.+)") ) labels: workload_type: barepod record: namespace_workload_pod:kube_pod_owner:relabel - expr: | max by (cluster, namespace, workload, pod) ( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="Node"}, "workload", "$1", "pod", "(.+)") ) labels: workload_type: staticpod record: namespace_workload_pod:kube_pod_owner:relabel - expr: | group by (cluster, namespace, workload, workload_type, pod) ( label_join( label_join( group by (cluster, namespace, job_name, pod) ( label_join( kube_pod_owner{job="kube-state-metrics", owner_kind="Job"} , "job_name", "", "owner_name") ) * on (cluster, namespace, job_name) group_left(owner_kind, owner_name) group by (cluster, namespace, job_name, owner_kind, owner_name) ( kube_job_owner{job="kube-state-metrics", owner_kind!="Pod", owner_kind!=""} ) , "workload", "", "owner_name") , "workload_type", "", "owner_kind") OR label_replace( label_replace( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="ReplicaSet"} , "replicaset", "$1", "owner_name", "(.+)" ) * on(cluster, namespace, replicaset) group_left(owner_kind, owner_name) group by (cluster, namespace, replicaset, owner_kind, owner_name) ( kube_replicaset_owner{job="kube-state-metrics", owner_kind!="Deployment", owner_kind!=""} ) , "workload", "$1", "owner_name", "(.+)") OR label_replace( group by (cluster, namespace, pod, owner_name, owner_kind) ( kube_pod_owner{job="kube-state-metrics", owner_kind!="ReplicaSet", owner_kind!="DaemonSet", owner_kind!="StatefulSet", owner_kind!="Job", owner_kind!="Node", owner_kind!=""} ) , "workload", "$1", "owner_name", "(.+)" ) , "workload_type", "$1", "owner_kind", "(.+)") ) record: namespace_workload_pod:kube_pod_owner:relabel - name: kube-scheduler.rules rules: - expr: | histogram_quantile(0.99, sum(rate(scheduler_e2e_scheduling_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) labels: quantile: "0.99" record: cluster_quantile:scheduler_e2e_scheduling_duration_seconds:histogram_quantile - expr: | histogram_quantile(0.99, sum(rate(scheduler_scheduling_algorithm_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) labels: quantile: "0.99" record: cluster_quantile:scheduler_scheduling_algorithm_duration_seconds:histogram_quantile - expr: | histogram_quantile(0.99, sum(rate(scheduler_binding_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) labels: quantile: "0.99" record: cluster_quantile:scheduler_binding_duration_seconds:histogram_quantile - expr: | histogram_quantile(0.9, sum(rate(scheduler_e2e_scheduling_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) labels: quantile: "0.9" record: cluster_quantile:scheduler_e2e_scheduling_duration_seconds:histogram_quantile - expr: | histogram_quantile(0.9, sum(rate(scheduler_scheduling_algorithm_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) labels: quantile: "0.9" record: cluster_quantile:scheduler_scheduling_algorithm_duration_seconds:histogram_quantile - expr: | histogram_quantile(0.9, sum(rate(scheduler_binding_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) labels: quantile: "0.9" record: cluster_quantile:scheduler_binding_duration_seconds:histogram_quantile - expr: | histogram_quantile(0.5, sum(rate(scheduler_e2e_scheduling_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) labels: quantile: "0.5" record: cluster_quantile:scheduler_e2e_scheduling_duration_seconds:histogram_quantile - expr: | histogram_quantile(0.5, sum(rate(scheduler_scheduling_algorithm_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) labels: quantile: "0.5" record: cluster_quantile:scheduler_scheduling_algorithm_duration_seconds:histogram_quantile - expr: | histogram_quantile(0.5, sum(rate(scheduler_binding_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) labels: quantile: "0.5" record: cluster_quantile:scheduler_binding_duration_seconds:histogram_quantile - name: node.rules rules: - expr: | topk by(cluster, namespace, pod) (1, max by (cluster, node, namespace, pod) ( label_replace(kube_pod_info{job="kube-state-metrics",node!=""}, "pod", "$1", "pod", "(.*)") )) record: 'node_namespace_pod:kube_pod_info:' - expr: | count by (cluster, node) ( node_cpu_seconds_total{mode="idle",job="node-exporter"} * on (cluster, namespace, pod) group_left(node) topk by(cluster, namespace, pod) (1, node_namespace_pod:kube_pod_info:) ) record: node:node_num_cpu:sum - expr: | sum( node_memory_MemAvailable_bytes{job="node-exporter"} or ( node_memory_Buffers_bytes{job="node-exporter"} + node_memory_Cached_bytes{job="node-exporter"} + node_memory_MemFree_bytes{job="node-exporter"} + node_memory_Slab_bytes{job="node-exporter"} ) ) by (cluster) record: :node_memory_MemAvailable_bytes:sum - expr: | avg by (cluster, node) ( sum without (mode) ( rate(node_cpu_seconds_total{mode!="idle",mode!="iowait",mode!="steal",job="node-exporter"}[5m]) ) ) record: node:node_cpu_utilization:ratio_rate5m - expr: | avg by (cluster) ( node:node_cpu_utilization:ratio_rate5m ) record: cluster:node_cpu:ratio_rate5m - name: kubelet.rules rules: - expr: | histogram_quantile( 0.99, sum(rate(kubelet_pleg_relist_duration_seconds_bucket{job="kubelet", metrics_path="/metrics"}[5m])) by (cluster, instance, le) * on(cluster, instance) group_left (node) max by (cluster, instance, node) (kubelet_node_name{job="kubelet", metrics_path="/metrics"}) ) labels: quantile: "0.99" record: node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile - expr: | histogram_quantile( 0.9, sum(rate(kubelet_pleg_relist_duration_seconds_bucket{job="kubelet", metrics_path="/metrics"}[5m])) by (cluster, instance, le) * on(cluster, instance) group_left (node) max by (cluster, instance, node) (kubelet_node_name{job="kubelet", metrics_path="/metrics"}) ) labels: quantile: "0.9" record: node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile - expr: | histogram_quantile( 0.5, sum(rate(kubelet_pleg_relist_duration_seconds_bucket{job="kubelet", metrics_path="/metrics"}[5m])) by (cluster, instance, le) * on(cluster, instance) group_left (node) max by (cluster, instance, node) (kubelet_node_name{job="kubelet", metrics_path="/metrics"}) ) labels: quantile: "0.5" record: node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile ================================================ FILE: hack/config/monitoring/kube-prometheus/kubernetesControlPlane-serviceMonitorApiserver.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/component: kubernetes app.kubernetes.io/name: apiserver app.kubernetes.io/part-of: kube-prometheus name: kube-apiserver namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 30s metricRelabelings: - action: drop regex: kubelet_(pod_worker_latency_microseconds|pod_start_latency_microseconds|cgroup_manager_latency_microseconds|pod_worker_start_latency_microseconds|pleg_relist_latency_microseconds|pleg_relist_interval_microseconds|runtime_operations|runtime_operations_latency_microseconds|runtime_operations_errors|eviction_stats_age_microseconds|device_plugin_registration_count|device_plugin_alloc_latency_microseconds|network_plugin_operations_latency_microseconds) sourceLabels: - __name__ - action: drop regex: scheduler_(e2e_scheduling_latency_microseconds|scheduling_algorithm_predicate_evaluation|scheduling_algorithm_priority_evaluation|scheduling_algorithm_preemption_evaluation|scheduling_algorithm_latency_microseconds|binding_latency_microseconds|scheduling_latency_seconds) sourceLabels: - __name__ - action: drop regex: apiserver_(request_count|request_latencies|request_latencies_summary|dropped_requests|storage_data_key_generation_latencies_microseconds|storage_transformation_failures_total|storage_transformation_latencies_microseconds|proxy_tunnel_sync_latency_secs|longrunning_gauge|registered_watchers|storage_db_total_size_in_bytes|flowcontrol_request_concurrency_limit|flowcontrol_request_concurrency_in_use) sourceLabels: - __name__ - action: drop regex: kubelet_docker_(operations|operations_latency_microseconds|operations_errors|operations_timeout) sourceLabels: - __name__ - action: drop regex: reflector_(items_per_list|items_per_watch|list_duration_seconds|lists_total|short_watches_total|watch_duration_seconds|watches_total) sourceLabels: - __name__ - action: drop regex: etcd_(helper_cache_hit_count|helper_cache_miss_count|helper_cache_entry_count|object_counts|request_cache_get_latencies_summary|request_cache_add_latencies_summary|request_latencies_summary) sourceLabels: - __name__ - action: drop regex: transformation_(transformation_latencies_microseconds|failures_total) sourceLabels: - __name__ - action: drop regex: (admission_quota_controller_adds|admission_quota_controller_depth|admission_quota_controller_longest_running_processor_microseconds|admission_quota_controller_queue_latency|admission_quota_controller_unfinished_work_seconds|admission_quota_controller_work_duration|APIServiceOpenAPIAggregationControllerQueue1_adds|APIServiceOpenAPIAggregationControllerQueue1_depth|APIServiceOpenAPIAggregationControllerQueue1_longest_running_processor_microseconds|APIServiceOpenAPIAggregationControllerQueue1_queue_latency|APIServiceOpenAPIAggregationControllerQueue1_retries|APIServiceOpenAPIAggregationControllerQueue1_unfinished_work_seconds|APIServiceOpenAPIAggregationControllerQueue1_work_duration|APIServiceRegistrationController_adds|APIServiceRegistrationController_depth|APIServiceRegistrationController_longest_running_processor_microseconds|APIServiceRegistrationController_queue_latency|APIServiceRegistrationController_retries|APIServiceRegistrationController_unfinished_work_seconds|APIServiceRegistrationController_work_duration|autoregister_adds|autoregister_depth|autoregister_longest_running_processor_microseconds|autoregister_queue_latency|autoregister_retries|autoregister_unfinished_work_seconds|autoregister_work_duration|AvailableConditionController_adds|AvailableConditionController_depth|AvailableConditionController_longest_running_processor_microseconds|AvailableConditionController_queue_latency|AvailableConditionController_retries|AvailableConditionController_unfinished_work_seconds|AvailableConditionController_work_duration|crd_autoregistration_controller_adds|crd_autoregistration_controller_depth|crd_autoregistration_controller_longest_running_processor_microseconds|crd_autoregistration_controller_queue_latency|crd_autoregistration_controller_retries|crd_autoregistration_controller_unfinished_work_seconds|crd_autoregistration_controller_work_duration|crdEstablishing_adds|crdEstablishing_depth|crdEstablishing_longest_running_processor_microseconds|crdEstablishing_queue_latency|crdEstablishing_retries|crdEstablishing_unfinished_work_seconds|crdEstablishing_work_duration|crd_finalizer_adds|crd_finalizer_depth|crd_finalizer_longest_running_processor_microseconds|crd_finalizer_queue_latency|crd_finalizer_retries|crd_finalizer_unfinished_work_seconds|crd_finalizer_work_duration|crd_naming_condition_controller_adds|crd_naming_condition_controller_depth|crd_naming_condition_controller_longest_running_processor_microseconds|crd_naming_condition_controller_queue_latency|crd_naming_condition_controller_retries|crd_naming_condition_controller_unfinished_work_seconds|crd_naming_condition_controller_work_duration|crd_openapi_controller_adds|crd_openapi_controller_depth|crd_openapi_controller_longest_running_processor_microseconds|crd_openapi_controller_queue_latency|crd_openapi_controller_retries|crd_openapi_controller_unfinished_work_seconds|crd_openapi_controller_work_duration|DiscoveryController_adds|DiscoveryController_depth|DiscoveryController_longest_running_processor_microseconds|DiscoveryController_queue_latency|DiscoveryController_retries|DiscoveryController_unfinished_work_seconds|DiscoveryController_work_duration|kubeproxy_sync_proxy_rules_latency_microseconds|non_structural_schema_condition_controller_adds|non_structural_schema_condition_controller_depth|non_structural_schema_condition_controller_longest_running_processor_microseconds|non_structural_schema_condition_controller_queue_latency|non_structural_schema_condition_controller_retries|non_structural_schema_condition_controller_unfinished_work_seconds|non_structural_schema_condition_controller_work_duration|rest_client_request_latency_seconds|storage_operation_errors_total|storage_operation_status_count) sourceLabels: - __name__ - action: drop regex: etcd_(debugging|disk|server).* sourceLabels: - __name__ - action: drop regex: apiserver_admission_controller_admission_latencies_seconds_.* sourceLabels: - __name__ - action: drop regex: apiserver_admission_step_admission_latencies_seconds_.* sourceLabels: - __name__ - action: drop regex: (apiserver_request|apiserver_request_sli|etcd_request)_duration_seconds_bucket;(0.15|0.25|0.3|0.35|0.4|0.45|0.6|0.7|0.8|0.9|1.25|1.5|1.75|2.5|3|3.5|4.5|6|7|8|9|15|25|30|50) sourceLabels: - __name__ - le - action: drop regex: apiserver_request_body_size_bytes_bucket;(150000|350000|550000|650000|850000|950000|(1\.15|1\.35|1\.55|1\.65|1\.85|1\.95|2\.15|2\.35|2\.55|2\.65|2\.85|2\.95)e\+06) sourceLabels: - __name__ - le port: https scheme: https tlsConfig: caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt serverName: kubernetes - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 5s metricRelabelings: - action: drop regex: process_start_time_seconds sourceLabels: - __name__ path: /metrics/slis port: https scheme: https tlsConfig: caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt serverName: kubernetes jobLabel: component namespaceSelector: matchNames: - default selector: matchLabels: component: apiserver provider: kubernetes ================================================ FILE: hack/config/monitoring/kube-prometheus/kubernetesControlPlane-serviceMonitorCoreDNS.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/component: kubernetes app.kubernetes.io/name: coredns app.kubernetes.io/part-of: kube-prometheus name: coredns namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 15s metricRelabelings: - action: drop regex: coredns_cache_misses_total sourceLabels: - __name__ port: metrics jobLabel: app.kubernetes.io/name namespaceSelector: matchNames: - kube-system selector: matchLabels: k8s-app: kube-dns ================================================ FILE: hack/config/monitoring/kube-prometheus/kubernetesControlPlane-serviceMonitorKubeControllerManager.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/component: kubernetes app.kubernetes.io/name: kube-controller-manager app.kubernetes.io/part-of: kube-prometheus name: kube-controller-manager namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 30s metricRelabelings: - action: drop regex: kubelet_(pod_worker_latency_microseconds|pod_start_latency_microseconds|cgroup_manager_latency_microseconds|pod_worker_start_latency_microseconds|pleg_relist_latency_microseconds|pleg_relist_interval_microseconds|runtime_operations|runtime_operations_latency_microseconds|runtime_operations_errors|eviction_stats_age_microseconds|device_plugin_registration_count|device_plugin_alloc_latency_microseconds|network_plugin_operations_latency_microseconds) sourceLabels: - __name__ - action: drop regex: scheduler_(e2e_scheduling_latency_microseconds|scheduling_algorithm_predicate_evaluation|scheduling_algorithm_priority_evaluation|scheduling_algorithm_preemption_evaluation|scheduling_algorithm_latency_microseconds|binding_latency_microseconds|scheduling_latency_seconds) sourceLabels: - __name__ - action: drop regex: apiserver_(request_count|request_latencies|request_latencies_summary|dropped_requests|storage_data_key_generation_latencies_microseconds|storage_transformation_failures_total|storage_transformation_latencies_microseconds|proxy_tunnel_sync_latency_secs|longrunning_gauge|registered_watchers|storage_db_total_size_in_bytes|flowcontrol_request_concurrency_limit|flowcontrol_request_concurrency_in_use) sourceLabels: - __name__ - action: drop regex: kubelet_docker_(operations|operations_latency_microseconds|operations_errors|operations_timeout) sourceLabels: - __name__ - action: drop regex: reflector_(items_per_list|items_per_watch|list_duration_seconds|lists_total|short_watches_total|watch_duration_seconds|watches_total) sourceLabels: - __name__ - action: drop regex: etcd_(helper_cache_hit_count|helper_cache_miss_count|helper_cache_entry_count|object_counts|request_cache_get_latencies_summary|request_cache_add_latencies_summary|request_latencies_summary) sourceLabels: - __name__ - action: drop regex: transformation_(transformation_latencies_microseconds|failures_total) sourceLabels: - __name__ - action: drop regex: (admission_quota_controller_adds|admission_quota_controller_depth|admission_quota_controller_longest_running_processor_microseconds|admission_quota_controller_queue_latency|admission_quota_controller_unfinished_work_seconds|admission_quota_controller_work_duration|APIServiceOpenAPIAggregationControllerQueue1_adds|APIServiceOpenAPIAggregationControllerQueue1_depth|APIServiceOpenAPIAggregationControllerQueue1_longest_running_processor_microseconds|APIServiceOpenAPIAggregationControllerQueue1_queue_latency|APIServiceOpenAPIAggregationControllerQueue1_retries|APIServiceOpenAPIAggregationControllerQueue1_unfinished_work_seconds|APIServiceOpenAPIAggregationControllerQueue1_work_duration|APIServiceRegistrationController_adds|APIServiceRegistrationController_depth|APIServiceRegistrationController_longest_running_processor_microseconds|APIServiceRegistrationController_queue_latency|APIServiceRegistrationController_retries|APIServiceRegistrationController_unfinished_work_seconds|APIServiceRegistrationController_work_duration|autoregister_adds|autoregister_depth|autoregister_longest_running_processor_microseconds|autoregister_queue_latency|autoregister_retries|autoregister_unfinished_work_seconds|autoregister_work_duration|AvailableConditionController_adds|AvailableConditionController_depth|AvailableConditionController_longest_running_processor_microseconds|AvailableConditionController_queue_latency|AvailableConditionController_retries|AvailableConditionController_unfinished_work_seconds|AvailableConditionController_work_duration|crd_autoregistration_controller_adds|crd_autoregistration_controller_depth|crd_autoregistration_controller_longest_running_processor_microseconds|crd_autoregistration_controller_queue_latency|crd_autoregistration_controller_retries|crd_autoregistration_controller_unfinished_work_seconds|crd_autoregistration_controller_work_duration|crdEstablishing_adds|crdEstablishing_depth|crdEstablishing_longest_running_processor_microseconds|crdEstablishing_queue_latency|crdEstablishing_retries|crdEstablishing_unfinished_work_seconds|crdEstablishing_work_duration|crd_finalizer_adds|crd_finalizer_depth|crd_finalizer_longest_running_processor_microseconds|crd_finalizer_queue_latency|crd_finalizer_retries|crd_finalizer_unfinished_work_seconds|crd_finalizer_work_duration|crd_naming_condition_controller_adds|crd_naming_condition_controller_depth|crd_naming_condition_controller_longest_running_processor_microseconds|crd_naming_condition_controller_queue_latency|crd_naming_condition_controller_retries|crd_naming_condition_controller_unfinished_work_seconds|crd_naming_condition_controller_work_duration|crd_openapi_controller_adds|crd_openapi_controller_depth|crd_openapi_controller_longest_running_processor_microseconds|crd_openapi_controller_queue_latency|crd_openapi_controller_retries|crd_openapi_controller_unfinished_work_seconds|crd_openapi_controller_work_duration|DiscoveryController_adds|DiscoveryController_depth|DiscoveryController_longest_running_processor_microseconds|DiscoveryController_queue_latency|DiscoveryController_retries|DiscoveryController_unfinished_work_seconds|DiscoveryController_work_duration|kubeproxy_sync_proxy_rules_latency_microseconds|non_structural_schema_condition_controller_adds|non_structural_schema_condition_controller_depth|non_structural_schema_condition_controller_longest_running_processor_microseconds|non_structural_schema_condition_controller_queue_latency|non_structural_schema_condition_controller_retries|non_structural_schema_condition_controller_unfinished_work_seconds|non_structural_schema_condition_controller_work_duration|rest_client_request_latency_seconds|storage_operation_errors_total|storage_operation_status_count) sourceLabels: - __name__ - action: drop regex: etcd_(debugging|disk|request|server).* sourceLabels: - __name__ port: https-metrics scheme: https tlsConfig: insecureSkipVerify: true - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 5s metricRelabelings: - action: drop regex: process_start_time_seconds sourceLabels: - __name__ path: /metrics/slis port: https-metrics scheme: https tlsConfig: insecureSkipVerify: true jobLabel: app.kubernetes.io/name namespaceSelector: matchNames: - kube-system selector: matchLabels: app.kubernetes.io/name: kube-controller-manager ================================================ FILE: hack/config/monitoring/kube-prometheus/kubernetesControlPlane-serviceMonitorKubeScheduler.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/component: kubernetes app.kubernetes.io/name: kube-scheduler app.kubernetes.io/part-of: kube-prometheus name: kube-scheduler namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 30s port: https-metrics scheme: https tlsConfig: insecureSkipVerify: true - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 5s metricRelabelings: - action: drop regex: process_start_time_seconds sourceLabels: - __name__ path: /metrics/slis port: https-metrics scheme: https tlsConfig: insecureSkipVerify: true jobLabel: app.kubernetes.io/name namespaceSelector: matchNames: - kube-system selector: matchLabels: app.kubernetes.io/name: kube-scheduler ================================================ FILE: hack/config/monitoring/kube-prometheus/kubernetesControlPlane-serviceMonitorKubelet.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/component: kubernetes app.kubernetes.io/name: kubelet app.kubernetes.io/part-of: kube-prometheus name: kubelet namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token honorLabels: true interval: 30s metricRelabelings: - action: drop regex: kubelet_(pod_worker_latency_microseconds|pod_start_latency_microseconds|cgroup_manager_latency_microseconds|pod_worker_start_latency_microseconds|pleg_relist_latency_microseconds|pleg_relist_interval_microseconds|runtime_operations|runtime_operations_latency_microseconds|runtime_operations_errors|eviction_stats_age_microseconds|device_plugin_registration_count|device_plugin_alloc_latency_microseconds|network_plugin_operations_latency_microseconds) sourceLabels: - __name__ - action: drop regex: scheduler_(e2e_scheduling_latency_microseconds|scheduling_algorithm_predicate_evaluation|scheduling_algorithm_priority_evaluation|scheduling_algorithm_preemption_evaluation|scheduling_algorithm_latency_microseconds|binding_latency_microseconds|scheduling_latency_seconds) sourceLabels: - __name__ - action: drop regex: apiserver_(request_count|request_latencies|request_latencies_summary|dropped_requests|storage_data_key_generation_latencies_microseconds|storage_transformation_failures_total|storage_transformation_latencies_microseconds|proxy_tunnel_sync_latency_secs|longrunning_gauge|registered_watchers|storage_db_total_size_in_bytes|flowcontrol_request_concurrency_limit|flowcontrol_request_concurrency_in_use) sourceLabels: - __name__ - action: drop regex: kubelet_docker_(operations|operations_latency_microseconds|operations_errors|operations_timeout) sourceLabels: - __name__ - action: drop regex: reflector_(items_per_list|items_per_watch|list_duration_seconds|lists_total|short_watches_total|watch_duration_seconds|watches_total) sourceLabels: - __name__ - action: drop regex: etcd_(helper_cache_hit_count|helper_cache_miss_count|helper_cache_entry_count|object_counts|request_cache_get_latencies_summary|request_cache_add_latencies_summary|request_latencies_summary) sourceLabels: - __name__ - action: drop regex: transformation_(transformation_latencies_microseconds|failures_total) sourceLabels: - __name__ - action: drop regex: (admission_quota_controller_adds|admission_quota_controller_depth|admission_quota_controller_longest_running_processor_microseconds|admission_quota_controller_queue_latency|admission_quota_controller_unfinished_work_seconds|admission_quota_controller_work_duration|APIServiceOpenAPIAggregationControllerQueue1_adds|APIServiceOpenAPIAggregationControllerQueue1_depth|APIServiceOpenAPIAggregationControllerQueue1_longest_running_processor_microseconds|APIServiceOpenAPIAggregationControllerQueue1_queue_latency|APIServiceOpenAPIAggregationControllerQueue1_retries|APIServiceOpenAPIAggregationControllerQueue1_unfinished_work_seconds|APIServiceOpenAPIAggregationControllerQueue1_work_duration|APIServiceRegistrationController_adds|APIServiceRegistrationController_depth|APIServiceRegistrationController_longest_running_processor_microseconds|APIServiceRegistrationController_queue_latency|APIServiceRegistrationController_retries|APIServiceRegistrationController_unfinished_work_seconds|APIServiceRegistrationController_work_duration|autoregister_adds|autoregister_depth|autoregister_longest_running_processor_microseconds|autoregister_queue_latency|autoregister_retries|autoregister_unfinished_work_seconds|autoregister_work_duration|AvailableConditionController_adds|AvailableConditionController_depth|AvailableConditionController_longest_running_processor_microseconds|AvailableConditionController_queue_latency|AvailableConditionController_retries|AvailableConditionController_unfinished_work_seconds|AvailableConditionController_work_duration|crd_autoregistration_controller_adds|crd_autoregistration_controller_depth|crd_autoregistration_controller_longest_running_processor_microseconds|crd_autoregistration_controller_queue_latency|crd_autoregistration_controller_retries|crd_autoregistration_controller_unfinished_work_seconds|crd_autoregistration_controller_work_duration|crdEstablishing_adds|crdEstablishing_depth|crdEstablishing_longest_running_processor_microseconds|crdEstablishing_queue_latency|crdEstablishing_retries|crdEstablishing_unfinished_work_seconds|crdEstablishing_work_duration|crd_finalizer_adds|crd_finalizer_depth|crd_finalizer_longest_running_processor_microseconds|crd_finalizer_queue_latency|crd_finalizer_retries|crd_finalizer_unfinished_work_seconds|crd_finalizer_work_duration|crd_naming_condition_controller_adds|crd_naming_condition_controller_depth|crd_naming_condition_controller_longest_running_processor_microseconds|crd_naming_condition_controller_queue_latency|crd_naming_condition_controller_retries|crd_naming_condition_controller_unfinished_work_seconds|crd_naming_condition_controller_work_duration|crd_openapi_controller_adds|crd_openapi_controller_depth|crd_openapi_controller_longest_running_processor_microseconds|crd_openapi_controller_queue_latency|crd_openapi_controller_retries|crd_openapi_controller_unfinished_work_seconds|crd_openapi_controller_work_duration|DiscoveryController_adds|DiscoveryController_depth|DiscoveryController_longest_running_processor_microseconds|DiscoveryController_queue_latency|DiscoveryController_retries|DiscoveryController_unfinished_work_seconds|DiscoveryController_work_duration|kubeproxy_sync_proxy_rules_latency_microseconds|non_structural_schema_condition_controller_adds|non_structural_schema_condition_controller_depth|non_structural_schema_condition_controller_longest_running_processor_microseconds|non_structural_schema_condition_controller_queue_latency|non_structural_schema_condition_controller_retries|non_structural_schema_condition_controller_unfinished_work_seconds|non_structural_schema_condition_controller_work_duration|rest_client_request_latency_seconds|storage_operation_errors_total|storage_operation_status_count) sourceLabels: - __name__ port: https-metrics relabelings: - action: replace sourceLabels: - __metrics_path__ targetLabel: metrics_path scheme: https tlsConfig: insecureSkipVerify: true - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token honorLabels: true honorTimestamps: false interval: 30s metricRelabelings: - action: drop regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s) sourceLabels: - __name__ - action: drop regex: (container_spec_.*|container_file_descriptors|container_sockets|container_threads_max|container_threads|container_start_time_seconds|container_last_seen);; sourceLabels: - __name__ - pod - namespace - action: drop regex: (container_blkio_device_usage_total);.+ sourceLabels: - __name__ - container path: /metrics/cadvisor port: https-metrics relabelings: - action: replace sourceLabels: - __metrics_path__ targetLabel: metrics_path scheme: https tlsConfig: insecureSkipVerify: true - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token honorLabels: true interval: 30s path: /metrics/probes port: https-metrics relabelings: - action: replace sourceLabels: - __metrics_path__ targetLabel: metrics_path scheme: https tlsConfig: insecureSkipVerify: true - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token honorLabels: true interval: 5s metricRelabelings: - action: drop regex: process_start_time_seconds sourceLabels: - __name__ path: /metrics/slis port: https-metrics relabelings: - action: replace sourceLabels: - __metrics_path__ targetLabel: metrics_path scheme: https tlsConfig: insecureSkipVerify: true jobLabel: app.kubernetes.io/name namespaceSelector: matchNames: - kube-system selector: matchLabels: app.kubernetes.io/name: kubelet ================================================ FILE: hack/config/monitoring/kube-prometheus/kustomization.yaml ================================================ # Code generated by update.sh, DO NOT EDIT. apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - blackboxExporter-clusterRole.yaml - blackboxExporter-clusterRoleBinding.yaml - blackboxExporter-configuration.yaml - blackboxExporter-deployment.yaml - blackboxExporter-networkPolicy.yaml - blackboxExporter-service.yaml - blackboxExporter-serviceAccount.yaml - blackboxExporter-serviceMonitor.yaml - grafana-config.yaml - grafana-dashboardDatasources.yaml - grafana-dashboardDefinitions.yaml - grafana-dashboardSources.yaml - grafana-deployment.yaml - grafana-networkPolicy.yaml - grafana-prometheusRule.yaml - grafana-service.yaml - grafana-serviceAccount.yaml - grafana-serviceMonitor.yaml - kubePrometheus-prometheusRule.yaml - kubernetesControlPlane-prometheusRule.yaml - kubernetesControlPlane-serviceMonitorApiserver.yaml - kubernetesControlPlane-serviceMonitorCoreDNS.yaml - kubernetesControlPlane-serviceMonitorKubeControllerManager.yaml - kubernetesControlPlane-serviceMonitorKubelet.yaml - kubernetesControlPlane-serviceMonitorKubeScheduler.yaml - kubeStateMetrics-clusterRole.yaml - kubeStateMetrics-clusterRoleBinding.yaml - kubeStateMetrics-deployment.yaml - kubeStateMetrics-networkPolicy.yaml - kubeStateMetrics-prometheusRule.yaml - kubeStateMetrics-service.yaml - kubeStateMetrics-serviceAccount.yaml - kubeStateMetrics-serviceMonitor.yaml - nodeExporter-clusterRole.yaml - nodeExporter-clusterRoleBinding.yaml - nodeExporter-daemonset.yaml - nodeExporter-networkPolicy.yaml - nodeExporter-prometheusRule.yaml - nodeExporter-service.yaml - nodeExporter-serviceAccount.yaml - nodeExporter-serviceMonitor.yaml - prometheus-clusterRole.yaml - prometheus-clusterRoleBinding.yaml - prometheus-networkPolicy.yaml - prometheus-prometheus.yaml - prometheus-prometheusRule.yaml - prometheus-roleBindingConfig.yaml - prometheus-roleBindingSpecificNamespaces.yaml - prometheus-roleConfig.yaml - prometheus-roleSpecificNamespaces.yaml - prometheus-service.yaml - prometheus-serviceAccount.yaml - prometheus-serviceMonitor.yaml - prometheusAdapter-clusterRole.yaml - prometheusAdapter-clusterRoleAggregatedMetricsReader.yaml - prometheusAdapter-clusterRoleBinding.yaml - prometheusAdapter-clusterRoleBindingDelegator.yaml - prometheusAdapter-clusterRoleServerResources.yaml - prometheusAdapter-configMap.yaml - prometheusAdapter-deployment.yaml - prometheusAdapter-networkPolicy.yaml - prometheusAdapter-podDisruptionBudget.yaml - prometheusAdapter-roleBindingAuthReader.yaml - prometheusAdapter-service.yaml - prometheusAdapter-serviceAccount.yaml - prometheusAdapter-serviceMonitor.yaml - prometheusOperator-clusterRole.yaml - prometheusOperator-clusterRoleBinding.yaml - prometheusOperator-deployment.yaml - prometheusOperator-networkPolicy.yaml - prometheusOperator-prometheusRule.yaml - prometheusOperator-service.yaml - prometheusOperator-serviceAccount.yaml - prometheusOperator-serviceMonitor.yaml ================================================ FILE: hack/config/monitoring/kube-prometheus/nodeExporter-clusterRole.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 1.9.1 name: node-exporter rules: - apiGroups: - authentication.k8s.io resources: - tokenreviews verbs: - create - apiGroups: - authorization.k8s.io resources: - subjectaccessreviews verbs: - create ================================================ FILE: hack/config/monitoring/kube-prometheus/nodeExporter-clusterRoleBinding.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 1.9.1 name: node-exporter roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: node-exporter subjects: - kind: ServiceAccount name: node-exporter namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/nodeExporter-daemonset.yaml ================================================ apiVersion: apps/v1 kind: DaemonSet metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 1.9.1 name: node-exporter namespace: monitoring spec: selector: matchLabels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus template: metadata: annotations: kubectl.kubernetes.io/default-container: node-exporter labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 1.9.1 spec: automountServiceAccountToken: true containers: - args: - --web.listen-address=127.0.0.1:9101 - --path.sysfs=/host/sys - --path.rootfs=/host/root - --path.procfs=/host/root/proc - --path.udev.data=/host/root/run/udev/data - --no-collector.wifi - --no-collector.hwmon - --no-collector.btrfs - --collector.filesystem.mount-points-exclude=^/(dev|proc|sys|run/k3s/containerd/.+|var/lib/docker/.+|var/lib/kubelet/pods/.+)($|/) - --collector.netclass.ignored-devices=^(veth.*|[a-f0-9]{15})$ - --collector.netdev.device-exclude=^(veth.*|[a-f0-9]{15})$ image: quay.io/prometheus/node-exporter:v1.9.1 name: node-exporter resources: limits: cpu: 250m memory: 180Mi requests: cpu: 102m memory: 180Mi securityContext: allowPrivilegeEscalation: false capabilities: add: - SYS_TIME drop: - ALL readOnlyRootFilesystem: true volumeMounts: - mountPath: /host/sys mountPropagation: HostToContainer name: sys readOnly: true - mountPath: /host/root mountPropagation: HostToContainer name: root readOnly: true - args: - --secure-listen-address=[$(IP)]:9100 - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 - --upstream=http://127.0.0.1:9101/ env: - name: IP valueFrom: fieldRef: fieldPath: status.podIP image: quay.io/brancz/kube-rbac-proxy:v0.19.1 name: kube-rbac-proxy ports: - containerPort: 9100 hostPort: 9100 name: https resources: limits: cpu: 20m memory: 40Mi requests: cpu: 10m memory: 20Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65532 runAsNonRoot: true runAsUser: 65532 seccompProfile: type: RuntimeDefault hostNetwork: true hostPID: true nodeSelector: kubernetes.io/os: linux priorityClassName: system-cluster-critical securityContext: runAsGroup: 65534 runAsNonRoot: true runAsUser: 65534 serviceAccountName: node-exporter tolerations: - operator: Exists volumes: - hostPath: path: /sys name: sys - hostPath: path: / name: root updateStrategy: rollingUpdate: maxUnavailable: 10% type: RollingUpdate ================================================ FILE: hack/config/monitoring/kube-prometheus/nodeExporter-networkPolicy.yaml ================================================ apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 1.9.1 name: node-exporter namespace: monitoring spec: egress: - {} ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: prometheus ports: - port: 9100 protocol: TCP podSelector: matchLabels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus policyTypes: - Egress - Ingress ================================================ FILE: hack/config/monitoring/kube-prometheus/nodeExporter-prometheusRule.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 1.9.1 prometheus: k8s role: alert-rules name: node-exporter-rules namespace: monitoring spec: groups: - name: node-exporter rules: - alert: NodeFilesystemSpaceFillingUp annotations: description: Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left and is filling up. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodefilesystemspacefillingup summary: Filesystem is predicted to run out of space within the next 24 hours. expr: | ( node_filesystem_avail_bytes{job="node-exporter",fstype!="",mountpoint!=""} / node_filesystem_size_bytes{job="node-exporter",fstype!="",mountpoint!=""} * 100 < 15 and predict_linear(node_filesystem_avail_bytes{job="node-exporter",fstype!="",mountpoint!=""}[6h], 24*60*60) < 0 and node_filesystem_readonly{job="node-exporter",fstype!="",mountpoint!=""} == 0 ) for: 1h labels: severity: warning - alert: NodeFilesystemSpaceFillingUp annotations: description: Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left and is filling up fast. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodefilesystemspacefillingup summary: Filesystem is predicted to run out of space within the next 4 hours. expr: | ( node_filesystem_avail_bytes{job="node-exporter",fstype!="",mountpoint!=""} / node_filesystem_size_bytes{job="node-exporter",fstype!="",mountpoint!=""} * 100 < 10 and predict_linear(node_filesystem_avail_bytes{job="node-exporter",fstype!="",mountpoint!=""}[6h], 4*60*60) < 0 and node_filesystem_readonly{job="node-exporter",fstype!="",mountpoint!=""} == 0 ) for: 1h labels: severity: critical - alert: NodeFilesystemAlmostOutOfSpace annotations: description: Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodefilesystemalmostoutofspace summary: Filesystem has less than 5% space left. expr: | ( node_filesystem_avail_bytes{job="node-exporter",fstype!="",mountpoint!=""} / node_filesystem_size_bytes{job="node-exporter",fstype!="",mountpoint!=""} * 100 < 5 and node_filesystem_readonly{job="node-exporter",fstype!="",mountpoint!=""} == 0 ) for: 30m labels: severity: warning - alert: NodeFilesystemAlmostOutOfSpace annotations: description: Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available space left. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodefilesystemalmostoutofspace summary: Filesystem has less than 3% space left. expr: | ( node_filesystem_avail_bytes{job="node-exporter",fstype!="",mountpoint!=""} / node_filesystem_size_bytes{job="node-exporter",fstype!="",mountpoint!=""} * 100 < 3 and node_filesystem_readonly{job="node-exporter",fstype!="",mountpoint!=""} == 0 ) for: 30m labels: severity: critical - alert: NodeFilesystemFilesFillingUp annotations: description: Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left and is filling up. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodefilesystemfilesfillingup summary: Filesystem is predicted to run out of inodes within the next 24 hours. expr: | ( node_filesystem_files_free{job="node-exporter",fstype!="",mountpoint!=""} / node_filesystem_files{job="node-exporter",fstype!="",mountpoint!=""} * 100 < 40 and predict_linear(node_filesystem_files_free{job="node-exporter",fstype!="",mountpoint!=""}[6h], 24*60*60) < 0 and node_filesystem_readonly{job="node-exporter",fstype!="",mountpoint!=""} == 0 ) for: 1h labels: severity: warning - alert: NodeFilesystemFilesFillingUp annotations: description: Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left and is filling up fast. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodefilesystemfilesfillingup summary: Filesystem is predicted to run out of inodes within the next 4 hours. expr: | ( node_filesystem_files_free{job="node-exporter",fstype!="",mountpoint!=""} / node_filesystem_files{job="node-exporter",fstype!="",mountpoint!=""} * 100 < 20 and predict_linear(node_filesystem_files_free{job="node-exporter",fstype!="",mountpoint!=""}[6h], 4*60*60) < 0 and node_filesystem_readonly{job="node-exporter",fstype!="",mountpoint!=""} == 0 ) for: 1h labels: severity: critical - alert: NodeFilesystemAlmostOutOfFiles annotations: description: Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodefilesystemalmostoutoffiles summary: Filesystem has less than 5% inodes left. expr: | ( node_filesystem_files_free{job="node-exporter",fstype!="",mountpoint!=""} / node_filesystem_files{job="node-exporter",fstype!="",mountpoint!=""} * 100 < 5 and node_filesystem_readonly{job="node-exporter",fstype!="",mountpoint!=""} == 0 ) for: 1h labels: severity: warning - alert: NodeFilesystemAlmostOutOfFiles annotations: description: Filesystem on {{ $labels.device }}, mounted on {{ $labels.mountpoint }}, at {{ $labels.instance }} has only {{ printf "%.2f" $value }}% available inodes left. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodefilesystemalmostoutoffiles summary: Filesystem has less than 3% inodes left. expr: | ( node_filesystem_files_free{job="node-exporter",fstype!="",mountpoint!=""} / node_filesystem_files{job="node-exporter",fstype!="",mountpoint!=""} * 100 < 3 and node_filesystem_readonly{job="node-exporter",fstype!="",mountpoint!=""} == 0 ) for: 1h labels: severity: critical - alert: NodeNetworkReceiveErrs annotations: description: '{{ $labels.instance }} interface {{ $labels.device }} has encountered {{ printf "%.0f" $value }} receive errors in the last two minutes.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodenetworkreceiveerrs summary: Network interface is reporting many receive errors. expr: | rate(node_network_receive_errs_total{job="node-exporter"}[2m]) / rate(node_network_receive_packets_total{job="node-exporter"}[2m]) > 0.01 for: 1h labels: severity: warning - alert: NodeNetworkTransmitErrs annotations: description: '{{ $labels.instance }} interface {{ $labels.device }} has encountered {{ printf "%.0f" $value }} transmit errors in the last two minutes.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodenetworktransmiterrs summary: Network interface is reporting many transmit errors. expr: | rate(node_network_transmit_errs_total{job="node-exporter"}[2m]) / rate(node_network_transmit_packets_total{job="node-exporter"}[2m]) > 0.01 for: 1h labels: severity: warning - alert: NodeHighNumberConntrackEntriesUsed annotations: description: '{{ $labels.instance }} {{ $value | humanizePercentage }} of conntrack entries are used.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodehighnumberconntrackentriesused summary: Number of conntrack are getting close to the limit. expr: | (node_nf_conntrack_entries{job="node-exporter"} / node_nf_conntrack_entries_limit) > 0.75 labels: severity: warning - alert: NodeTextFileCollectorScrapeError annotations: description: Node Exporter text file collector on {{ $labels.instance }} failed to scrape. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodetextfilecollectorscrapeerror summary: Node Exporter text file collector failed to scrape. expr: | node_textfile_scrape_error{job="node-exporter"} == 1 labels: severity: warning - alert: NodeClockSkewDetected annotations: description: Clock at {{ $labels.instance }} is out of sync by more than 0.05s. Ensure NTP is configured correctly on this host. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodeclockskewdetected summary: Clock skew detected. expr: | ( node_timex_offset_seconds{job="node-exporter"} > 0.05 and deriv(node_timex_offset_seconds{job="node-exporter"}[5m]) >= 0 ) or ( node_timex_offset_seconds{job="node-exporter"} < -0.05 and deriv(node_timex_offset_seconds{job="node-exporter"}[5m]) <= 0 ) for: 10m labels: severity: warning - alert: NodeClockNotSynchronising annotations: description: Clock at {{ $labels.instance }} is not synchronising. Ensure NTP is configured on this host. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodeclocknotsynchronising summary: Clock not synchronising. expr: | min_over_time(node_timex_sync_status{job="node-exporter"}[5m]) == 0 and node_timex_maxerror_seconds{job="node-exporter"} >= 16 for: 10m labels: severity: warning - alert: NodeRAIDDegraded annotations: description: RAID array '{{ $labels.device }}' at {{ $labels.instance }} is in degraded state due to one or more disks failures. Number of spare drives is insufficient to fix issue automatically. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/noderaiddegraded summary: RAID Array is degraded. expr: | node_md_disks_required{job="node-exporter",device=~"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)"} - ignoring (state) (node_md_disks{state="active",job="node-exporter",device=~"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)"}) > 0 for: 15m labels: severity: critical - alert: NodeRAIDDiskFailure annotations: description: At least one device in RAID array at {{ $labels.instance }} failed. Array '{{ $labels.device }}' needs attention and possibly a disk swap. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/noderaiddiskfailure summary: Failed device in RAID array. expr: | node_md_disks{state="failed",job="node-exporter",device=~"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)"} > 0 labels: severity: warning - alert: NodeFileDescriptorLimit annotations: description: File descriptors limit at {{ $labels.instance }} is currently at {{ printf "%.2f" $value }}%. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodefiledescriptorlimit summary: Kernel is predicted to exhaust file descriptors limit soon. expr: | ( node_filefd_allocated{job="node-exporter"} * 100 / node_filefd_maximum{job="node-exporter"} > 70 ) for: 15m labels: severity: warning - alert: NodeFileDescriptorLimit annotations: description: File descriptors limit at {{ $labels.instance }} is currently at {{ printf "%.2f" $value }}%. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodefiledescriptorlimit summary: Kernel is predicted to exhaust file descriptors limit soon. expr: | ( node_filefd_allocated{job="node-exporter"} * 100 / node_filefd_maximum{job="node-exporter"} > 90 ) for: 15m labels: severity: critical - alert: NodeCPUHighUsage annotations: description: | CPU usage at {{ $labels.instance }} has been above 90% for the last 15 minutes, is currently at {{ printf "%.2f" $value }}%. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodecpuhighusage summary: High CPU usage. expr: | sum without(mode) (avg without (cpu) (rate(node_cpu_seconds_total{job="node-exporter", mode!~"idle|iowait"}[2m]))) * 100 > 90 for: 15m labels: severity: info - alert: NodeSystemSaturation annotations: description: | System load per core at {{ $labels.instance }} has been above 2 for the last 15 minutes, is currently at {{ printf "%.2f" $value }}. This might indicate this instance resources saturation and can cause it becoming unresponsive. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodesystemsaturation summary: System saturated, load per core is very high. expr: | node_load1{job="node-exporter"} / count without (cpu, mode) (node_cpu_seconds_total{job="node-exporter", mode="idle"}) > 2 for: 15m labels: severity: warning - alert: NodeMemoryMajorPagesFaults annotations: description: | Memory major pages are occurring at very high rate at {{ $labels.instance }}, 500 major page faults per second for the last 15 minutes, is currently at {{ printf "%.2f" $value }}. Please check that there is enough memory available at this instance. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodememorymajorpagesfaults summary: Memory major page faults are occurring at very high rate. expr: | rate(node_vmstat_pgmajfault{job="node-exporter"}[5m]) > 500 for: 15m labels: severity: warning - alert: NodeMemoryHighUtilization annotations: description: | Memory is filling up at {{ $labels.instance }}, has been above 90% for the last 15 minutes, is currently at {{ printf "%.2f" $value }}%. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodememoryhighutilization summary: Host is running out of memory. expr: | 100 - (node_memory_MemAvailable_bytes{job="node-exporter"} / node_memory_MemTotal_bytes{job="node-exporter"} * 100) > 90 for: 15m labels: severity: warning - alert: NodeDiskIOSaturation annotations: description: | Disk IO queue (aqu-sq) is high on {{ $labels.device }} at {{ $labels.instance }}, has been above 10 for the last 30 minutes, is currently at {{ printf "%.2f" $value }}. This symptom might indicate disk saturation. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodediskiosaturation summary: Disk IO queue is high. expr: | rate(node_disk_io_time_weighted_seconds_total{job="node-exporter", device=~"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)"}[5m]) > 10 for: 30m labels: severity: warning - alert: NodeSystemdServiceFailed annotations: description: Systemd service {{ $labels.name }} has entered failed state at {{ $labels.instance }} runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodesystemdservicefailed summary: Systemd service has entered failed state. expr: | node_systemd_unit_state{job="node-exporter", state="failed"} == 1 for: 5m labels: severity: warning - alert: NodeSystemdServiceCrashlooping annotations: description: Systemd service {{ $labels.name }} has being restarted too many times at {{ $labels.instance }} for the last 15 minutes. Please check if service is crash looping. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodesystemdservicecrashlooping summary: Systemd service keeps restaring, possibly crash looping. expr: | increase(node_systemd_service_restart_total{job="node-exporter"}[5m]) > 2 for: 15m labels: severity: warning - alert: NodeBondingDegraded annotations: description: Bonding interface {{ $labels.master }} on {{ $labels.instance }} is in degraded state due to one or more slave failures. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/node/nodebondingdegraded summary: Bonding interface is degraded expr: | (node_bonding_slaves - node_bonding_active) != 0 for: 5m labels: severity: warning - name: node-exporter.rules rules: - expr: | count without (cpu, mode) ( node_cpu_seconds_total{job="node-exporter",mode="idle"} ) record: instance:node_num_cpu:sum - expr: | 1 - avg without (cpu) ( sum without (mode) (rate(node_cpu_seconds_total{job="node-exporter", mode=~"idle|iowait|steal"}[5m])) ) record: instance:node_cpu_utilisation:rate5m - expr: | ( node_load1{job="node-exporter"} / instance:node_num_cpu:sum{job="node-exporter"} ) record: instance:node_load1_per_cpu:ratio - expr: | 1 - ( ( node_memory_MemAvailable_bytes{job="node-exporter"} or ( node_memory_Buffers_bytes{job="node-exporter"} + node_memory_Cached_bytes{job="node-exporter"} + node_memory_MemFree_bytes{job="node-exporter"} + node_memory_Slab_bytes{job="node-exporter"} ) ) / node_memory_MemTotal_bytes{job="node-exporter"} ) record: instance:node_memory_utilisation:ratio - expr: | rate(node_vmstat_pgmajfault{job="node-exporter"}[5m]) record: instance:node_vmstat_pgmajfault:rate5m - expr: | rate(node_disk_io_time_seconds_total{job="node-exporter", device=~"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)"}[5m]) record: instance_device:node_disk_io_time_seconds:rate5m - expr: | rate(node_disk_io_time_weighted_seconds_total{job="node-exporter", device=~"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)"}[5m]) record: instance_device:node_disk_io_time_weighted_seconds:rate5m - expr: | sum without (device) ( rate(node_network_receive_bytes_total{job="node-exporter", device!="lo"}[5m]) ) record: instance:node_network_receive_bytes_excluding_lo:rate5m - expr: | sum without (device) ( rate(node_network_transmit_bytes_total{job="node-exporter", device!="lo"}[5m]) ) record: instance:node_network_transmit_bytes_excluding_lo:rate5m - expr: | sum without (device) ( rate(node_network_receive_drop_total{job="node-exporter", device!="lo"}[5m]) ) record: instance:node_network_receive_drop_excluding_lo:rate5m - expr: | sum without (device) ( rate(node_network_transmit_drop_total{job="node-exporter", device!="lo"}[5m]) ) record: instance:node_network_transmit_drop_excluding_lo:rate5m ================================================ FILE: hack/config/monitoring/kube-prometheus/nodeExporter-service.yaml ================================================ apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 1.9.1 name: node-exporter namespace: monitoring spec: clusterIP: None ports: - name: https port: 9100 targetPort: https selector: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus ================================================ FILE: hack/config/monitoring/kube-prometheus/nodeExporter-serviceAccount.yaml ================================================ apiVersion: v1 automountServiceAccountToken: false kind: ServiceAccount metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 1.9.1 name: node-exporter namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/nodeExporter-serviceMonitor.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 1.9.1 name: node-exporter namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 15s port: https relabelings: - action: replace regex: (.*) replacement: $1 sourceLabels: - __meta_kubernetes_pod_node_name targetLabel: instance scheme: https tlsConfig: insecureSkipVerify: true jobLabel: app.kubernetes.io/name selector: matchLabels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheus-clusterRole.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s rules: - apiGroups: - "" resources: - nodes/metrics verbs: - get - nonResourceURLs: - /metrics - /metrics/slis verbs: - get ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheus-clusterRoleBinding.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: prometheus-k8s subjects: - kind: ServiceAccount name: prometheus-k8s namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheus-networkPolicy.yaml ================================================ apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s namespace: monitoring spec: egress: - {} ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: prometheus ports: - port: 9090 protocol: TCP - port: 8080 protocol: TCP - from: - podSelector: matchLabels: app.kubernetes.io/name: prometheus-adapter ports: - port: 9090 protocol: TCP - from: - podSelector: matchLabels: app.kubernetes.io/name: grafana ports: - port: 9090 protocol: TCP podSelector: matchLabels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus policyTypes: - Egress - Ingress ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheus-prometheus.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: k8s namespace: monitoring spec: alerting: alertmanagers: - apiVersion: v2 name: alertmanager-main namespace: monitoring port: web enableFeatures: [] externalLabels: {} image: quay.io/prometheus/prometheus:v3.5.0 nodeSelector: kubernetes.io/os: linux podMetadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 podMonitorNamespaceSelector: {} podMonitorSelector: {} probeNamespaceSelector: {} probeSelector: {} replicas: 2 resources: requests: memory: 400Mi ruleNamespaceSelector: {} ruleSelector: {} scrapeConfigNamespaceSelector: {} scrapeConfigSelector: {} securityContext: fsGroup: 2000 runAsNonRoot: true runAsUser: 1000 serviceAccountName: prometheus-k8s serviceMonitorNamespaceSelector: {} serviceMonitorSelector: {} version: 3.5.0 ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheus-prometheusRule.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 prometheus: k8s role: alert-rules name: prometheus-k8s-prometheus-rules namespace: monitoring spec: groups: - name: prometheus rules: - alert: PrometheusBadConfig annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} has failed to reload its configuration. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusbadconfig summary: Failed Prometheus configuration reload. expr: | # Without max_over_time, failed scrapes could create false negatives, see # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. max_over_time(prometheus_config_last_reload_successful{job="prometheus-k8s",namespace="monitoring"}[5m]) == 0 for: 10m labels: severity: critical - alert: PrometheusSDRefreshFailure annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} has failed to refresh SD with mechanism {{$labels.mechanism}}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheussdrefreshfailure summary: Failed Prometheus SD refresh. expr: | increase(prometheus_sd_refresh_failures_total{job="prometheus-k8s",namespace="monitoring"}[10m]) > 0 for: 20m labels: severity: warning - alert: PrometheusKubernetesListWatchFailures annotations: description: Kubernetes service discovery of Prometheus {{$labels.namespace}}/{{$labels.pod}} is experiencing {{ printf "%.0f" $value }} failures with LIST/WATCH requests to the Kubernetes API in the last 5 minutes. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheuskuberneteslistwatchfailures summary: Requests in Kubernetes SD are failing. expr: | increase(prometheus_sd_kubernetes_failures_total{job="prometheus-k8s",namespace="monitoring"}[5m]) > 0 for: 15m labels: severity: warning - alert: PrometheusNotificationQueueRunningFull annotations: description: Alert notification queue of Prometheus {{$labels.namespace}}/{{$labels.pod}} is running full. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusnotificationqueuerunningfull summary: Prometheus alert notification queue predicted to run full in less than 30m. expr: | # Without min_over_time, failed scrapes could create false negatives, see # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. ( predict_linear(prometheus_notifications_queue_length{job="prometheus-k8s",namespace="monitoring"}[5m], 60 * 30) > min_over_time(prometheus_notifications_queue_capacity{job="prometheus-k8s",namespace="monitoring"}[5m]) ) for: 15m labels: severity: warning - alert: PrometheusErrorSendingAlertsToSomeAlertmanagers annotations: description: '{{ printf "%.1f" $value }}% of alerts sent by Prometheus {{$labels.namespace}}/{{$labels.pod}} to Alertmanager {{$labels.alertmanager}} were affected by errors.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheuserrorsendingalertstosomealertmanagers summary: More than 1% of alerts sent by Prometheus to a specific Alertmanager were affected by errors. expr: | ( rate(prometheus_notifications_errors_total{job="prometheus-k8s",namespace="monitoring"}[5m]) / rate(prometheus_notifications_sent_total{job="prometheus-k8s",namespace="monitoring"}[5m]) ) * 100 > 1 for: 15m labels: severity: warning - alert: PrometheusNotConnectedToAlertmanagers annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} is not connected to any Alertmanagers. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusnotconnectedtoalertmanagers summary: Prometheus is not connected to any Alertmanagers. expr: | # Without max_over_time, failed scrapes could create false negatives, see # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. max_over_time(prometheus_notifications_alertmanagers_discovered{job="prometheus-k8s",namespace="monitoring"}[5m]) < 1 for: 10m labels: severity: warning - alert: PrometheusTSDBReloadsFailing annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} has detected {{$value | humanize}} reload failures over the last 3h. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheustsdbreloadsfailing summary: Prometheus has issues reloading blocks from disk. expr: | increase(prometheus_tsdb_reloads_failures_total{job="prometheus-k8s",namespace="monitoring"}[3h]) > 0 for: 4h labels: severity: warning - alert: PrometheusTSDBCompactionsFailing annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} has detected {{$value | humanize}} compaction failures over the last 3h. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheustsdbcompactionsfailing summary: Prometheus has issues compacting blocks. expr: | increase(prometheus_tsdb_compactions_failed_total{job="prometheus-k8s",namespace="monitoring"}[3h]) > 0 for: 4h labels: severity: warning - alert: PrometheusNotIngestingSamples annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} is not ingesting samples. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusnotingestingsamples summary: Prometheus is not ingesting samples. expr: | ( sum without(type) (rate(prometheus_tsdb_head_samples_appended_total{job="prometheus-k8s",namespace="monitoring"}[5m])) <= 0 and ( sum without(scrape_job) (prometheus_target_metadata_cache_entries{job="prometheus-k8s",namespace="monitoring"}) > 0 or sum without(rule_group) (prometheus_rule_group_rules{job="prometheus-k8s",namespace="monitoring"}) > 0 ) ) for: 10m labels: severity: warning - alert: PrometheusDuplicateTimestamps annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} is dropping {{ printf "%.4g" $value }} samples/s with different values but duplicated timestamp. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusduplicatetimestamps summary: Prometheus is dropping samples with duplicate timestamps. expr: | rate(prometheus_target_scrapes_sample_duplicate_timestamp_total{job="prometheus-k8s",namespace="monitoring"}[5m]) > 0 for: 10m labels: severity: warning - alert: PrometheusOutOfOrderTimestamps annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} is dropping {{ printf "%.4g" $value }} samples/s with timestamps arriving out of order. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusoutofordertimestamps summary: Prometheus drops samples with out-of-order timestamps. expr: | rate(prometheus_target_scrapes_sample_out_of_order_total{job="prometheus-k8s",namespace="monitoring"}[5m]) > 0 for: 10m labels: severity: warning - alert: PrometheusRemoteStorageFailures annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} failed to send {{ printf "%.1f" $value }}% of the samples to {{ $labels.remote_name}}:{{ $labels.url }} runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusremotestoragefailures summary: Prometheus fails to send samples to remote storage. expr: | ( (rate(prometheus_remote_storage_failed_samples_total{job="prometheus-k8s",namespace="monitoring"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{job="prometheus-k8s",namespace="monitoring"}[5m])) / ( (rate(prometheus_remote_storage_failed_samples_total{job="prometheus-k8s",namespace="monitoring"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{job="prometheus-k8s",namespace="monitoring"}[5m])) + (rate(prometheus_remote_storage_succeeded_samples_total{job="prometheus-k8s",namespace="monitoring"}[5m]) or rate(prometheus_remote_storage_samples_total{job="prometheus-k8s",namespace="monitoring"}[5m])) ) ) * 100 > 1 for: 15m labels: severity: critical - alert: PrometheusRemoteWriteBehind annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} remote write is {{ printf "%.1f" $value }}s behind for {{ $labels.remote_name}}:{{ $labels.url }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusremotewritebehind summary: Prometheus remote write is behind. expr: | # Without max_over_time, failed scrapes could create false negatives, see # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. ( max_over_time(prometheus_remote_storage_highest_timestamp_in_seconds{job="prometheus-k8s",namespace="monitoring"}[5m]) - ignoring(remote_name, url) group_right max_over_time(prometheus_remote_storage_queue_highest_sent_timestamp_seconds{job="prometheus-k8s",namespace="monitoring"}[5m]) ) > 120 for: 15m labels: severity: critical - alert: PrometheusRemoteWriteDesiredShards annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} remote write desired shards calculation wants to run {{ $value }} shards for queue {{ $labels.remote_name}}:{{ $labels.url }}, which is more than the max of {{ printf `prometheus_remote_storage_shards_max{instance="%s",job="prometheus-k8s",namespace="monitoring"}` $labels.instance | query | first | value }}. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusremotewritedesiredshards summary: Prometheus remote write desired shards calculation wants to run more than configured max shards. expr: | # Without max_over_time, failed scrapes could create false negatives, see # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. ( max_over_time(prometheus_remote_storage_shards_desired{job="prometheus-k8s",namespace="monitoring"}[5m]) > max_over_time(prometheus_remote_storage_shards_max{job="prometheus-k8s",namespace="monitoring"}[5m]) ) for: 15m labels: severity: warning - alert: PrometheusRuleFailures annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} has failed to evaluate {{ printf "%.0f" $value }} rules in the last 5m. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusrulefailures summary: Prometheus is failing rule evaluations. expr: | increase(prometheus_rule_evaluation_failures_total{job="prometheus-k8s",namespace="monitoring"}[5m]) > 0 for: 15m labels: severity: critical - alert: PrometheusMissingRuleEvaluations annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} has missed {{ printf "%.0f" $value }} rule group evaluations in the last 5m. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusmissingruleevaluations summary: Prometheus is missing rule evaluations due to slow rule group evaluation. expr: | increase(prometheus_rule_group_iterations_missed_total{job="prometheus-k8s",namespace="monitoring"}[5m]) > 0 for: 15m labels: severity: warning - alert: PrometheusTargetLimitHit annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} has dropped {{ printf "%.0f" $value }} targets because the number of targets exceeded the configured target_limit. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheustargetlimithit summary: Prometheus has dropped targets because some scrape configs have exceeded the targets limit. expr: | increase(prometheus_target_scrape_pool_exceeded_target_limit_total{job="prometheus-k8s",namespace="monitoring"}[5m]) > 0 for: 15m labels: severity: warning - alert: PrometheusLabelLimitHit annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} has dropped {{ printf "%.0f" $value }} targets because some samples exceeded the configured label_limit, label_name_length_limit or label_value_length_limit. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheuslabellimithit summary: Prometheus has dropped targets because some scrape configs have exceeded the labels limit. expr: | increase(prometheus_target_scrape_pool_exceeded_label_limits_total{job="prometheus-k8s",namespace="monitoring"}[5m]) > 0 for: 15m labels: severity: warning - alert: PrometheusScrapeBodySizeLimitHit annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} has failed {{ printf "%.0f" $value }} scrapes in the last 5m because some targets exceeded the configured body_size_limit. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusscrapebodysizelimithit summary: Prometheus has dropped some targets that exceeded body size limit. expr: | increase(prometheus_target_scrapes_exceeded_body_size_limit_total{job="prometheus-k8s",namespace="monitoring"}[5m]) > 0 for: 15m labels: severity: warning - alert: PrometheusScrapeSampleLimitHit annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} has failed {{ printf "%.0f" $value }} scrapes in the last 5m because some targets exceeded the configured sample_limit. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusscrapesamplelimithit summary: Prometheus has failed scrapes that have exceeded the configured sample limit. expr: | increase(prometheus_target_scrapes_exceeded_sample_limit_total{job="prometheus-k8s",namespace="monitoring"}[5m]) > 0 for: 15m labels: severity: warning - alert: PrometheusTargetSyncFailure annotations: description: '{{ printf "%.0f" $value }} targets in Prometheus {{$labels.namespace}}/{{$labels.pod}} have failed to sync because invalid configuration was supplied.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheustargetsyncfailure summary: Prometheus has failed to sync targets. expr: | increase(prometheus_target_sync_failed_total{job="prometheus-k8s",namespace="monitoring"}[30m]) > 0 for: 5m labels: severity: critical - alert: PrometheusHighQueryLoad annotations: description: Prometheus {{$labels.namespace}}/{{$labels.pod}} query API has less than 20% available capacity in its query engine for the last 15 minutes. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheushighqueryload summary: Prometheus is reaching its maximum capacity serving concurrent requests. expr: | avg_over_time(prometheus_engine_queries{job="prometheus-k8s",namespace="monitoring"}[5m]) / max_over_time(prometheus_engine_queries_concurrent_max{job="prometheus-k8s",namespace="monitoring"}[5m]) > 0.8 for: 15m labels: severity: warning - alert: PrometheusErrorSendingAlertsToAnyAlertmanager annotations: description: '{{ printf "%.1f" $value }}% minimum errors while sending alerts from Prometheus {{$labels.namespace}}/{{$labels.pod}} to any Alertmanager.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheuserrorsendingalertstoanyalertmanager summary: Prometheus encounters more than 3% errors sending alerts to any Alertmanager. expr: | min without (alertmanager) ( rate(prometheus_notifications_errors_total{job="prometheus-k8s",namespace="monitoring",alertmanager!~``}[5m]) / rate(prometheus_notifications_sent_total{job="prometheus-k8s",namespace="monitoring",alertmanager!~``}[5m]) ) * 100 > 3 for: 15m labels: severity: critical ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheus-roleBindingConfig.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s-config namespace: monitoring roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: prometheus-k8s-config subjects: - kind: ServiceAccount name: prometheus-k8s namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheus-roleBindingSpecificNamespaces.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 items: - apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: prometheus-k8s subjects: - kind: ServiceAccount name: prometheus-k8s namespace: monitoring - apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s namespace: kube-system roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: prometheus-k8s subjects: - kind: ServiceAccount name: prometheus-k8s namespace: monitoring - apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s namespace: monitoring roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: prometheus-k8s subjects: - kind: ServiceAccount name: prometheus-k8s namespace: monitoring kind: RoleBindingList ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheus-roleConfig.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s-config namespace: monitoring rules: - apiGroups: - "" resources: - configmaps verbs: - get ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheus-roleSpecificNamespaces.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 items: - apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s namespace: default rules: - apiGroups: - "" resources: - services - endpoints - pods verbs: - get - list - watch - apiGroups: - extensions resources: - ingresses verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s namespace: kube-system rules: - apiGroups: - "" resources: - services - endpoints - pods verbs: - get - list - watch - apiGroups: - extensions resources: - ingresses verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s namespace: monitoring rules: - apiGroups: - "" resources: - services - endpoints - pods verbs: - get - list - watch - apiGroups: - extensions resources: - ingresses verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch kind: RoleList ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheus-service.yaml ================================================ apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s namespace: monitoring spec: ports: - name: web port: 9090 targetPort: web - name: reloader-web port: 8080 targetPort: reloader-web selector: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus sessionAffinity: ClientIP ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheus-serviceAccount.yaml ================================================ apiVersion: v1 automountServiceAccountToken: true kind: ServiceAccount metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheus-serviceMonitor.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 3.5.0 name: prometheus-k8s namespace: monitoring spec: endpoints: - interval: 30s port: web - interval: 30s port: reloader-web selector: matchLabels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusAdapter-clusterRole.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 name: prometheus-adapter rules: - apiGroups: - "" resources: - nodes - namespaces - pods - services verbs: - get - list - watch ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusAdapter-clusterRoleAggregatedMetricsReader.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 rbac.authorization.k8s.io/aggregate-to-admin: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-view: "true" name: system:aggregated-metrics-reader rules: - apiGroups: - metrics.k8s.io resources: - pods - nodes verbs: - get - list - watch ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusAdapter-clusterRoleBinding.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 name: prometheus-adapter roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: prometheus-adapter subjects: - kind: ServiceAccount name: prometheus-adapter namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusAdapter-clusterRoleBindingDelegator.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 name: resource-metrics:system:auth-delegator roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:auth-delegator subjects: - kind: ServiceAccount name: prometheus-adapter namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusAdapter-clusterRoleServerResources.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 name: resource-metrics-server-resources rules: - apiGroups: - metrics.k8s.io resources: - '*' verbs: - '*' ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusAdapter-configMap.yaml ================================================ apiVersion: v1 data: config.yaml: |- "resourceRules": "cpu": "containerLabel": "container" "containerQuery": | sum by (<<.GroupBy>>) ( irate ( container_cpu_usage_seconds_total{<<.LabelMatchers>>,container!="",pod!=""}[120s] ) ) "nodeQuery": | sum by (<<.GroupBy>>) ( 1 - irate( node_cpu_seconds_total{mode="idle"}[60s] ) * on(namespace, pod) group_left(node) ( node_namespace_pod:kube_pod_info:{<<.LabelMatchers>>} ) ) or sum by (<<.GroupBy>>) ( 1 - irate( windows_cpu_time_total{mode="idle", job="windows-exporter",<<.LabelMatchers>>}[4m] ) ) "resources": "overrides": "namespace": "resource": "namespace" "node": "resource": "node" "pod": "resource": "pod" "memory": "containerLabel": "container" "containerQuery": | sum by (<<.GroupBy>>) ( container_memory_working_set_bytes{<<.LabelMatchers>>,container!="",pod!=""} ) "nodeQuery": | sum by (<<.GroupBy>>) ( node_memory_MemTotal_bytes{job="node-exporter",<<.LabelMatchers>>} - node_memory_MemAvailable_bytes{job="node-exporter",<<.LabelMatchers>>} ) or sum by (<<.GroupBy>>) ( windows_cs_physical_memory_bytes{job="windows-exporter",<<.LabelMatchers>>} - windows_memory_available_bytes{job="windows-exporter",<<.LabelMatchers>>} ) "resources": "overrides": "instance": "resource": "node" "namespace": "resource": "namespace" "pod": "resource": "pod" "window": "5m" kind: ConfigMap metadata: labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 name: adapter-config namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusAdapter-deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 name: prometheus-adapter namespace: monitoring spec: replicas: 2 selector: matchLabels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 template: metadata: annotations: checksum.config/md5: 3b1ebf7df0232d1675896f67b66373db labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 spec: automountServiceAccountToken: true containers: - args: - --cert-dir=/var/run/serving-cert - --config=/etc/adapter/config.yaml - --metrics-relist-interval=1m - --prometheus-url=http://prometheus-k8s.monitoring.svc:9090/ - --secure-port=6443 - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA image: registry.k8s.io/prometheus-adapter/prometheus-adapter:v0.12.0 livenessProbe: failureThreshold: 5 httpGet: path: /livez port: https scheme: HTTPS periodSeconds: 5 name: prometheus-adapter ports: - containerPort: 6443 name: https readinessProbe: failureThreshold: 5 httpGet: path: /readyz port: https scheme: HTTPS periodSeconds: 5 resources: limits: cpu: 250m memory: 180Mi requests: cpu: 102m memory: 180Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault startupProbe: failureThreshold: 18 httpGet: path: /livez port: https scheme: HTTPS periodSeconds: 10 volumeMounts: - mountPath: /tmp name: tmpfs readOnly: false - mountPath: /var/run/serving-cert name: volume-serving-cert readOnly: false - mountPath: /etc/adapter name: config readOnly: false nodeSelector: kubernetes.io/os: linux serviceAccountName: prometheus-adapter volumes: - emptyDir: {} name: tmpfs - emptyDir: {} name: volume-serving-cert - configMap: name: adapter-config name: config ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusAdapter-networkPolicy.yaml ================================================ apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 name: prometheus-adapter namespace: monitoring spec: egress: - {} ingress: - {} podSelector: matchLabels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus policyTypes: - Egress - Ingress ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusAdapter-podDisruptionBudget.yaml ================================================ apiVersion: policy/v1 kind: PodDisruptionBudget metadata: labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 name: prometheus-adapter namespace: monitoring spec: minAvailable: 1 selector: matchLabels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusAdapter-roleBindingAuthReader.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 name: resource-metrics-auth-reader namespace: kube-system roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: extension-apiserver-authentication-reader subjects: - kind: ServiceAccount name: prometheus-adapter namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusAdapter-service.yaml ================================================ apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 name: prometheus-adapter namespace: monitoring spec: ports: - name: https port: 443 targetPort: 6443 selector: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusAdapter-serviceAccount.yaml ================================================ apiVersion: v1 automountServiceAccountToken: false kind: ServiceAccount metadata: labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 name: prometheus-adapter namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusAdapter-serviceMonitor.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.12.0 name: prometheus-adapter namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 30s metricRelabelings: - action: drop regex: (apiserver_client_certificate_.*|apiserver_envelope_.*|apiserver_flowcontrol_.*|apiserver_storage_.*|apiserver_webhooks_.*|workqueue_.*) sourceLabels: - __name__ port: https scheme: https tlsConfig: insecureSkipVerify: true selector: matchLabels: app.kubernetes.io/component: metrics-adapter app.kubernetes.io/name: prometheus-adapter app.kubernetes.io/part-of: kube-prometheus ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusOperator-clusterRole.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.85.0 name: prometheus-operator rules: - apiGroups: - monitoring.coreos.com resources: - alertmanagers - alertmanagers/finalizers - alertmanagers/status - alertmanagerconfigs - prometheuses - prometheuses/finalizers - prometheuses/status - prometheusagents - prometheusagents/finalizers - prometheusagents/status - thanosrulers - thanosrulers/finalizers - thanosrulers/status - scrapeconfigs - servicemonitors - servicemonitors/status - podmonitors - probes - prometheusrules verbs: - '*' - apiGroups: - apps resources: - statefulsets verbs: - '*' - apiGroups: - "" resources: - configmaps - secrets verbs: - '*' - apiGroups: - "" resources: - pods verbs: - list - delete - apiGroups: - "" resources: - services - services/finalizers verbs: - get - create - update - delete - apiGroups: - "" resources: - nodes verbs: - list - watch - apiGroups: - "" resources: - namespaces verbs: - get - list - watch - apiGroups: - "" resources: - events verbs: - patch - create - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiGroups: - storage.k8s.io resources: - storageclasses verbs: - get - apiGroups: - "" resources: - endpoints verbs: - get - create - update - delete - apiGroups: - authentication.k8s.io resources: - tokenreviews verbs: - create - apiGroups: - authorization.k8s.io resources: - subjectaccessreviews verbs: - create ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusOperator-clusterRoleBinding.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.85.0 name: prometheus-operator roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: prometheus-operator subjects: - kind: ServiceAccount name: prometheus-operator namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusOperator-deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.85.0 name: prometheus-operator namespace: monitoring spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus template: metadata: annotations: kubectl.kubernetes.io/default-container: prometheus-operator labels: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.85.0 spec: automountServiceAccountToken: true containers: - args: - --kubelet-service=kube-system/kubelet - --prometheus-config-reloader=quay.io/prometheus-operator/prometheus-config-reloader:v0.85.0 - --kubelet-endpoints=true - --kubelet-endpointslice=false env: - name: GOGC value: "30" image: quay.io/prometheus-operator/prometheus-operator:v0.85.0 name: prometheus-operator ports: - containerPort: 8080 name: http resources: limits: cpu: 200m memory: 200Mi requests: cpu: 100m memory: 100Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true - args: - --secure-listen-address=:8443 - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 - --upstream=http://127.0.0.1:8080/ image: quay.io/brancz/kube-rbac-proxy:v0.19.1 name: kube-rbac-proxy ports: - containerPort: 8443 name: https resources: limits: cpu: 20m memory: 40Mi requests: cpu: 10m memory: 20Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65532 runAsNonRoot: true runAsUser: 65532 seccompProfile: type: RuntimeDefault nodeSelector: kubernetes.io/os: linux securityContext: runAsGroup: 65534 runAsNonRoot: true runAsUser: 65534 seccompProfile: type: RuntimeDefault serviceAccountName: prometheus-operator ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusOperator-networkPolicy.yaml ================================================ apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.85.0 name: prometheus-operator namespace: monitoring spec: egress: - {} ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: prometheus ports: - port: 8443 protocol: TCP podSelector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus policyTypes: - Egress - Ingress ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusOperator-prometheusRule.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.85.0 prometheus: k8s role: alert-rules name: prometheus-operator-rules namespace: monitoring spec: groups: - name: prometheus-operator rules: - alert: PrometheusOperatorListErrors annotations: description: Errors while performing List operations in controller {{$labels.controller}} in {{$labels.namespace}} namespace. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus-operator/prometheusoperatorlisterrors summary: Errors while performing list operations in controller. expr: | (sum by (cluster,controller,namespace) (rate(prometheus_operator_list_operations_failed_total{job="prometheus-operator",namespace="monitoring"}[10m])) / sum by (cluster,controller,namespace) (rate(prometheus_operator_list_operations_total{job="prometheus-operator",namespace="monitoring"}[10m]))) > 0.4 for: 15m labels: severity: warning - alert: PrometheusOperatorWatchErrors annotations: description: Errors while performing watch operations in controller {{$labels.controller}} in {{$labels.namespace}} namespace. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus-operator/prometheusoperatorwatcherrors summary: Errors while performing watch operations in controller. expr: | (sum by (cluster,controller,namespace) (rate(prometheus_operator_watch_operations_failed_total{job="prometheus-operator",namespace="monitoring"}[5m])) / sum by (cluster,controller,namespace) (rate(prometheus_operator_watch_operations_total{job="prometheus-operator",namespace="monitoring"}[5m]))) > 0.4 for: 15m labels: severity: warning - alert: PrometheusOperatorSyncFailed annotations: description: Controller {{ $labels.controller }} in {{ $labels.namespace }} namespace fails to reconcile {{ $value }} objects. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus-operator/prometheusoperatorsyncfailed summary: Last controller reconciliation failed expr: | min_over_time(prometheus_operator_syncs{status="failed",job="prometheus-operator",namespace="monitoring"}[5m]) > 0 for: 10m labels: severity: warning - alert: PrometheusOperatorReconcileErrors annotations: description: '{{ $value | humanizePercentage }} of reconciling operations failed for {{ $labels.controller }} controller in {{ $labels.namespace }} namespace.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus-operator/prometheusoperatorreconcileerrors summary: Errors while reconciling objects. expr: | (sum by (cluster,controller,namespace) (rate(prometheus_operator_reconcile_errors_total{job="prometheus-operator",namespace="monitoring"}[5m]))) / (sum by (cluster,controller,namespace) (rate(prometheus_operator_reconcile_operations_total{job="prometheus-operator",namespace="monitoring"}[5m]))) > 0.1 for: 10m labels: severity: warning - alert: PrometheusOperatorStatusUpdateErrors annotations: description: '{{ $value | humanizePercentage }} of status update operations failed for {{ $labels.controller }} controller in {{ $labels.namespace }} namespace.' runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus-operator/prometheusoperatorstatusupdateerrors summary: Errors while updating objects status. expr: | (sum by (cluster,controller,namespace) (rate(prometheus_operator_status_update_errors_total{job="prometheus-operator",namespace="monitoring"}[5m]))) / (sum by (cluster,controller,namespace) (rate(prometheus_operator_status_update_operations_total{job="prometheus-operator",namespace="monitoring"}[5m]))) > 0.1 for: 10m labels: severity: warning - alert: PrometheusOperatorNodeLookupErrors annotations: description: Errors while reconciling Prometheus in {{ $labels.namespace }} Namespace. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus-operator/prometheusoperatornodelookuperrors summary: Errors while reconciling Prometheus. expr: | rate(prometheus_operator_node_address_lookup_errors_total{job="prometheus-operator",namespace="monitoring"}[5m]) > 0.1 for: 10m labels: severity: warning - alert: PrometheusOperatorNotReady annotations: description: Prometheus operator in {{ $labels.namespace }} namespace isn't ready to reconcile {{ $labels.controller }} resources. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus-operator/prometheusoperatornotready summary: Prometheus operator not ready expr: | min by (cluster,controller,namespace) (max_over_time(prometheus_operator_ready{job="prometheus-operator",namespace="monitoring"}[5m]) == 0) for: 5m labels: severity: warning - alert: PrometheusOperatorRejectedResources annotations: description: Prometheus operator in {{ $labels.namespace }} namespace rejected {{ printf "%0.0f" $value }} {{ $labels.controller }}/{{ $labels.resource }} resources. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus-operator/prometheusoperatorrejectedresources summary: Resources rejected by Prometheus operator expr: | min_over_time(prometheus_operator_managed_resources{state="rejected",job="prometheus-operator",namespace="monitoring"}[5m]) > 0 for: 5m labels: severity: warning - name: config-reloaders rules: - alert: ConfigReloaderSidecarErrors annotations: description: |- Errors encountered while the {{$labels.pod}} config-reloader sidecar attempts to sync config in {{$labels.namespace}} namespace. As a result, configuration for service running in {{$labels.pod}} may be stale and cannot be updated anymore. runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus-operator/configreloadersidecarerrors summary: config-reloader sidecar has not had a successful reload for 10m expr: | max_over_time(reloader_last_reload_successful{namespace=~".+"}[5m]) == 0 for: 10m labels: severity: warning ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusOperator-service.yaml ================================================ apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.85.0 name: prometheus-operator namespace: monitoring spec: clusterIP: None ports: - name: https port: 8443 targetPort: https selector: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusOperator-serviceAccount.yaml ================================================ apiVersion: v1 automountServiceAccountToken: false kind: ServiceAccount metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.85.0 name: prometheus-operator namespace: monitoring ================================================ FILE: hack/config/monitoring/kube-prometheus/prometheusOperator-serviceMonitor.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.85.0 name: prometheus-operator namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token honorLabels: true port: https scheme: https tlsConfig: insecureSkipVerify: true selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.85.0 ================================================ FILE: hack/config/monitoring/shoot/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../default - storageclass.yaml patches: - path: patch_prometheus.yaml # drop ServiceMonitors for control plane components (not reachable in Shoot cluster) - patch: | apiVersion: monitoring.coreos.com/v1 metadata: name: kube-apiserver namespace: monitoring kind: ServiceMonitor $patch: delete - patch: | apiVersion: monitoring.coreos.com/v1 metadata: name: kube-controller-manager namespace: monitoring kind: ServiceMonitor $patch: delete - patch: | apiVersion: monitoring.coreos.com/v1 metadata: name: kube-scheduler namespace: monitoring kind: ServiceMonitor $patch: delete ================================================ FILE: hack/config/monitoring/shoot/patch_prometheus.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: name: k8s namespace: monitoring spec: retention: 30d retentionSize: 90GiB storage: volumeClaimTemplate: metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus name: prometheus spec: accessModes: - ReadWriteOnce resources: requests: storage: 100Gi storageClassName: premium-perf1-stackit ================================================ FILE: hack/config/monitoring/shoot/storageclass.yaml ================================================ apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: gce-ssd parameters: type: pd-ssd allowVolumeExpansion: true provisioner: pd.csi.storage.gke.io reclaimPolicy: Delete volumeBindingMode: WaitForFirstConsumer ================================================ FILE: hack/config/monitoring/update.sh ================================================ #!/usr/bin/env bash set -o errexit set -o nounset set -o pipefail cd "$(dirname "${BASH_SOURCE[0]}")" # renovate: datasource=github-releases depName=prometheus-operator/kube-prometheus KUBE_PROMETHEUS_VERSION=v0.16.0 echo "> Fetching kube-prometheus@$KUBE_PROMETHEUS_VERSION" tmp_dir=$(mktemp -d) trap 'rm -rf "$tmp_dir"' EXIT tarball="$tmp_dir/archive.tar.gz" curl -sSLo "$tarball" https://github.com/prometheus-operator/kube-prometheus/archive/refs/tags/$KUBE_PROMETHEUS_VERSION.tar.gz prometheus_operator_version=$(tar -xzf "$tarball" --wildcards "kube-prometheus-*/manifests/prometheusOperator-deployment.yaml" -O | grep app.kubernetes.io/version | head -1 | awk '{print $2}') echo "Included prometheus-operator version: $prometheus_operator_version" echo "> Updating CRDs" pushd crds >/dev/null rm *.yaml tar -xzf "$tarball" --strip-components=3 --wildcards "kube-prometheus-*/manifests/setup/*.yaml" # drop unneeded stuff rm namespace.yaml cat < README.md The CRDs in this directory were downloaded from https://github.com/prometheus-operator/kube-prometheus/tree/$KUBE_PROMETHEUS_VERSION/manifests/setup. Bump the version in [\`$(basename $0)\`](../$(basename $0)) and run the script to update the CRDs. EOF cat < kustomization.yaml # Code generated by $(basename $0), DO NOT EDIT. apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization labels: - includeSelectors: true pairs: app.kubernetes.io/name: prometheus-operator app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: $prometheus_operator_version resources: $(ls *.yaml | sed 's/^/- /') EOF popd >/dev/null echo "> Updating kube-prometheus" pushd kube-prometheus >/dev/null rm *.yaml tar -xzf "$tarball" --strip-components=2 --wildcards "kube-prometheus-*/manifests/*.yaml" # drop unneeded stuff rm -rf setup rm alertmanager-*.yaml # this will override metrics-server APIService (conflicts with gardener-resource-manager), drop it rm prometheusAdapter-apiService.yaml # PDB with minAvailable=1 for a single-replica StatefulSet blocks rolling node upgrades forever rm prometheus-podDisruptionBudget.yaml cat < README.md The manifests in this directory were downloaded from https://github.com/prometheus-operator/kube-prometheus/tree/$KUBE_PROMETHEUS_VERSION/manifests. Bump the version in [\`$(basename $0)\`](../$(basename $0)) and run the script to update the CRDs. EOF cat < kustomization.yaml # Code generated by $(basename $0), DO NOT EDIT. apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: $(ls *.yaml | sed 's/^/- /') EOF popd >/dev/null ================================================ FILE: hack/config/policy/ci/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - no-requests.yaml ================================================ FILE: hack/config/policy/ci/no-requests.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: no-requests-limits spec: failurePolicy: Fail rules: # drop resource requests to allow scheduling all controller instances on a resource-restricted kind cluster (e.g., in CI) - name: no-requests-limits match: any: - resources: kinds: - Pod selector: matchExpressions: - key: app.kubernetes.io/name operator: In values: - controller-sharding - key: app.kubernetes.io/component operator: In values: - sharder - checksum-controller operations: - CREATE - resources: kinds: - Pod selector: matchExpressions: - key: app.kubernetes.io/name operator: In values: - webhosting-operator operations: - CREATE mutate: foreach: - list: request.object.spec.containers patchStrategicMerge: spec: containers: - (name): "{{element.name}}" resources: null ================================================ FILE: hack/config/policy/controlplane/etcd-main.yaml ================================================ apiVersion: kyverno.io/v1 kind: Policy metadata: name: etcd-main namespace: shoot--ixywdlfvei--sharding spec: failurePolicy: Fail rules: # set static requests/limits on etcd-main to ensure similar evaluation environment between load test runs - name: resources match: any: - resources: kinds: - Pod selector: matchLabels: app.kubernetes.io/name: etcd-main mutate: patchStrategicMerge: spec: containers: - name: etcd resources: requests: cpu: 12000m memory: 12Gi limits: cpu: 12000m memory: 12Gi # set GOMAXPROCS to CPU quota to minimize goroutine scheduling contention (CPU throttling) env: - name: GOMAXPROCS value: "12" - name: disable-vpa match: any: - resources: kinds: - VerticalPodAutoscaler names: - etcd-main mutate: patchStrategicMerge: spec: updatePolicy: updateMode: Off ================================================ FILE: hack/config/policy/controlplane/kube-apiserver.yaml ================================================ apiVersion: kyverno.io/v1 kind: Policy metadata: name: kube-apiserver namespace: shoot--ixywdlfvei--sharding spec: failurePolicy: Fail rules: # set static replicas on kube-apiserver to ensure similar evaluation environment between load test runs - name: disable-hpa match: any: - resources: kinds: - HorizontalPodAutoscaler names: - kube-apiserver mutate: patchStrategicMerge: spec: minReplicas: 4 maxReplicas: 4 # set static requests/limits on kube-apiserver to ensure similar evaluation environment between load test runs - name: resources match: any: - resources: kinds: - Pod selector: matchLabels: app: kubernetes role: apiserver mutate: patchStrategicMerge: spec: containers: - name: kube-apiserver resources: requests: cpu: 12000m memory: 12Gi limits: cpu: 12000m memory: 12Gi # set GOMAXPROCS to CPU quota to minimize goroutine scheduling contention (CPU throttling) env: - name: GOMAXPROCS value: "12" - name: disable-vpa match: any: - resources: kinds: - VerticalPodAutoscaler names: - kube-apiserver-vpa mutate: patchStrategicMerge: spec: updatePolicy: updateMode: Off ================================================ FILE: hack/config/policy/controlplane/kube-controller-manager.yaml ================================================ apiVersion: kyverno.io/v1 kind: Policy metadata: name: kube-controller-manager namespace: shoot--ixywdlfvei--sharding spec: failurePolicy: Ignore rules: # set static requests/limits on kube-controller-manager to ensure similar evaluation environment between load test runs - name: resources match: any: - resources: kinds: - Pod selector: matchLabels: app: kubernetes role: controller-manager mutate: patchStrategicMerge: spec: containers: - name: kube-controller-manager resources: requests: cpu: 6000m memory: 6Gi limits: cpu: 6000m memory: 6Gi # set GOMAXPROCS to CPU quota to minimize goroutine scheduling contention (CPU throttling) env: - name: GOMAXPROCS value: "6" - name: disable-vpa match: any: - resources: kinds: - VerticalPodAutoscaler names: - kube-controller-manager-vpa mutate: patchStrategicMerge: spec: updatePolicy: updateMode: Off # disable kube-controller-manager's client-side rate limits similar to webhosting-operator - name: disable-rate-limits match: any: - resources: kinds: - Deployment names: - kube-controller-manager mutate: patchesJson6902: |- - op: add path: /spec/template/spec/containers/0/command/- value: "--kube-api-qps=-1" # disable HTTP2 in kube-controller-manager's so that API requests are distributed across API server instances - name: disable-http2 match: any: - resources: kinds: - Deployment names: - kube-controller-manager mutate: patchStrategicMerge: spec: template: spec: containers: - name: kube-controller-manager env: - name: DISABLE_HTTP2 value: "true" ================================================ FILE: hack/config/policy/controlplane/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization # This kustomization contains policies for manipulating shoot control plane components. # For this to work, kyverno needs to be installed on the seed cluster. resources: - etcd-main.yaml - kube-apiserver.yaml - kube-controller-manager.yaml ================================================ FILE: hack/config/policy/shoot/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - sharder-scheduling.yaml ================================================ FILE: hack/config/policy/shoot/sharder-scheduling.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: sharder-scheduling spec: failurePolicy: Fail rules: # schedule sharder on dedicated worker pool for better isolation in load tests - name: add-scheduling-constraints match: any: - resources: kinds: - Pod namespaces: - sharding-system selector: matchLabels: app.kubernetes.io/name: controller-sharding app.kubernetes.io/component: sharder operations: - CREATE mutate: patchesJson6902: |- - op: add path: "/spec/tolerations/-" value: {"key":"dedicated-for","operator":"Equal","value":"sharding","effect":"NoSchedule"} - op: add path: "/spec/affinity/nodeAffinity/requiredDuringSchedulingIgnoredDuringExecution/nodeSelectorTerms/-" value: {"matchExpressions": [{"key":"dedicated-for","operator":"In","values":["sharding"]}]} ================================================ FILE: hack/config/profiling/ensure-admin-password.sh ================================================ #!/usr/bin/env bash dir="$(dirname "$0")" password_file="$dir/parca_password.secret.txt" auth_file="$dir/parca_auth.secret.txt" [ -f "$password_file" ] && [ -f "$auth_file" ] && exit 0 cat /dev/urandom | tr -dc "a-zA-Z0-9" | head -c 32 > "$password_file" cat "$password_file" | htpasswd -i -c "$auth_file" parca ================================================ FILE: hack/config/profiling/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - https://github.com/parca-dev/parca/releases/download/v0.24.2/kubernetes-manifest.yaml - parca_ingress.yaml - parca_pvc.yaml # grant parca running in namespace "parca" permissions required for service discovery in namespace # "sharding-system" and scrape the pprof endpoints of sharder - rbac_sharder.yaml generatorOptions: disableNameSuffixHash: true labels: app.kubernetes.io/component: observability app.kubernetes.io/instance: parca app.kubernetes.io/name: parca configMapGenerator: - name: parca namespace: parca behavior: merge files: - parca.yaml=parca_config.yaml secretGenerator: - name: parca-basic-auth namespace: parca literals: - username=parca files: - password=parca_password.secret.txt - auth=parca_auth.secret.txt patches: - path: patch_deployment_pvc.yaml - target: kind: Deployment name: parca namespace: parca patch: | - op: add path: /spec/template/spec/containers/0/args/- value: --enable-persistence - op: add path: /spec/template/spec/containers/0/args/- value: --storage-path=/var/lib/parca - op: add path: /spec/template/spec/containers/0/args/- value: --storage-enable-wal ================================================ FILE: hack/config/profiling/parca_config.yaml ================================================ object_storage: bucket: config: directory: /var/lib/parca type: FILESYSTEM scrape_configs: # heavily inspired by the prometheus scrape config generated by prometheus-operator for sharder ServiceMonitor - job_name: sharder scrape_interval: 2s scrape_timeout: 4s scheme: https authorization: type: Bearer credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token tls_config: insecure_skip_verify: true kubernetes_sd_configs: - role: endpoints namespaces: names: - sharding-system relabel_configs: - action: keep source_labels: - __meta_kubernetes_service_label_app_kubernetes_io_name - __meta_kubernetes_service_labelpresent_app_kubernetes_io_name regex: (controller-sharding);true - action: keep source_labels: - __meta_kubernetes_service_label_app_kubernetes_io_component - __meta_kubernetes_service_labelpresent_app_kubernetes_io_component regex: (sharder);true - action: keep source_labels: - __meta_kubernetes_endpoint_port_name regex: metrics - source_labels: - __meta_kubernetes_endpoint_address_target_kind - __meta_kubernetes_endpoint_address_target_name separator: ; regex: Node;(.*) replacement: ${1} target_label: node - source_labels: - __meta_kubernetes_endpoint_address_target_kind - __meta_kubernetes_endpoint_address_target_name separator: ; regex: Pod;(.*) replacement: ${1} target_label: pod - source_labels: - __meta_kubernetes_namespace target_label: namespace - source_labels: - __meta_kubernetes_service_name target_label: service - source_labels: - __meta_kubernetes_pod_name target_label: pod - source_labels: - __meta_kubernetes_pod_container_name target_label: container - source_labels: - __meta_kubernetes_service_name target_label: job replacement: ${1} - target_label: endpoint replacement: metrics - target_label: job replacement: sharder action: replace # heavily inspired by the prometheus scrape config generated by prometheus-operator for webhosting-operator ServiceMonitor - job_name: webhosting-operator scrape_interval: 2s scrape_timeout: 4s scheme: https authorization: type: Bearer credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token tls_config: insecure_skip_verify: true kubernetes_sd_configs: - role: endpoints namespaces: names: - webhosting-system relabel_configs: - action: keep source_labels: - __meta_kubernetes_service_label_app_kubernetes_io_name - __meta_kubernetes_service_labelpresent_app_kubernetes_io_name regex: (webhosting-operator);true - action: keep source_labels: - __meta_kubernetes_endpoint_port_name regex: https - source_labels: - __meta_kubernetes_endpoint_address_target_kind - __meta_kubernetes_endpoint_address_target_name separator: ; regex: Node;(.*) replacement: ${1} target_label: node - source_labels: - __meta_kubernetes_endpoint_address_target_kind - __meta_kubernetes_endpoint_address_target_name separator: ; regex: Pod;(.*) replacement: ${1} target_label: pod - source_labels: - __meta_kubernetes_namespace target_label: namespace - source_labels: - __meta_kubernetes_service_name target_label: service - source_labels: - __meta_kubernetes_pod_name target_label: pod - source_labels: - __meta_kubernetes_pod_container_name target_label: container - source_labels: - __meta_kubernetes_service_name target_label: job replacement: ${1} - target_label: endpoint replacement: https - target_label: job replacement: webhosting-operator action: replace ================================================ FILE: hack/config/profiling/parca_ingress.yaml ================================================ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: cert-manager.io/cluster-issuer: letsencrypt-http01 nginx.ingress.kubernetes.io/auth-type: basic nginx.ingress.kubernetes.io/auth-secret: parca-basic-auth nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required' labels: app.kubernetes.io/component: observability app.kubernetes.io/instance: parca app.kubernetes.io/name: parca name: parca namespace: parca spec: ingressClassName: nginx rules: - host: parca.webhosting.timebertt.dev http: paths: - backend: service: name: parca port: name: http path: / pathType: Prefix tls: - hosts: - parca.webhosting.timebertt.dev secretName: parca-tls ================================================ FILE: hack/config/profiling/parca_pvc.yaml ================================================ apiVersion: v1 kind: PersistentVolumeClaim metadata: labels: app.kubernetes.io/component: observability app.kubernetes.io/instance: parca app.kubernetes.io/name: parca name: parca namespace: parca spec: accessModes: - ReadWriteOnce resources: requests: storage: 150Gi ================================================ FILE: hack/config/profiling/patch_deployment_pvc.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: parca namespace: parca spec: # set replicas and strategy to play nicely with PVC replicas: 1 strategy: type: Recreate rollingUpdate: null template: spec: volumes: - name: data emptyDir: null persistentVolumeClaim: claimName: parca ================================================ FILE: hack/config/profiling/rbac_sharder.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: parca-service-discovery namespace: sharding-system rules: - apiGroups: - "" resources: - services - endpoints - pods verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: parca-service-discovery namespace: sharding-system roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: parca-service-discovery subjects: - kind: ServiceAccount name: parca namespace: parca --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: observability app.kubernetes.io/instance: parca app.kubernetes.io/name: parca name: parca-sharder-pprof-reader roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: sharding:sharder:pprof-reader subjects: - kind: ServiceAccount name: parca namespace: parca ================================================ FILE: hack/config/sharder/devel/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../../../config/default patches: - target: group: apps kind: Deployment name: sharder namespace: sharding-system patch: | - op: add path: /spec/template/spec/containers/0/args/- value: --zap-devel ================================================ FILE: hack/config/sharder/host/config.yaml ================================================ apiVersion: config.sharding.timebertt.dev/v1alpha1 kind: SharderConfig webhook: server: certDir: hack/config/certificates/host certName: webhook-server.pem keyName: webhook-server-key.pem config: annotations: cert-manager.io/inject-ca-from-secret: sharding-system/webhook-ca clientConfig: url: https://host.docker.internal:9443/ controller: sharder: syncPeriod: 30s ================================================ FILE: hack/config/shoot.yaml ================================================ apiVersion: core.gardener.cloud/v1beta1 kind: Shoot metadata: name: sharding namespace: garden-ixywdlfvei-ccknp spec: addons: kubernetesDashboard: enabled: false cloudProfile: kind: CloudProfile name: stackit cloudProfileName: stackit controlPlane: highAvailability: failureTolerance: type: zone credentialsBindingName: ixywdlfvei-infrastructure hibernation: schedules: - location: Europe/Berlin start: 0 5 * * * kubernetes: kubeAPIServer: requests: maxMutatingInflight: 200 maxNonMutatingInflight: 400 kubeControllerManager: nodeCIDRMaskSize: 24 kubeProxy: mode: IPTables kubelet: serializeImagePulls: false version: "1.33" maintenance: autoUpdate: kubernetesVersion: true machineImageVersion: true timeWindow: begin: 030000+0200 end: 040000+0200 networking: ipFamilies: - IPv4 nodes: 10.250.0.0/16 pods: 100.64.0.0/13 services: 100.82.0.0/16 providerConfig: apiVersion: calico.networking.extensions.gardener.cloud/v1alpha1 kind: NetworkConfig backend: bird ipv4: mode: Always pool: ipip type: calico provider: controlPlaneConfig: apiVersion: stackit.provider.extensions.gardener.cloud/v1alpha1 kind: ControlPlaneConfig infrastructureConfig: apiVersion: stackit.provider.extensions.gardener.cloud/v1alpha1 kind: InfrastructureConfig floatingPoolName: floating-net networks: workers: 10.250.0.0/16 type: stackit workers: # runs system and monitoring components (default worker pool) - name: system cri: name: containerd machine: architecture: amd64 image: name: coreos type: g1a.8d maxSurge: 1 maxUnavailable: 0 maximum: 2 minimum: 1 systemComponents: allow: true volume: size: 50Gi type: storage_premium_perf1 zones: - eu01-3 # runs sharding components and webhosting-operator - name: sharding cri: name: containerd labels: dedicated-for: sharding machine: architecture: amd64 image: name: coreos type: g1a.8d maxSurge: 1 maxUnavailable: 0 maximum: 3 minimum: 2 systemComponents: allow: false taints: - effect: NoSchedule key: dedicated-for value: sharding volume: size: 50Gi type: storage_premium_perf1 zones: - eu01-3 # runs experiment (optional) - name: experiment cri: name: containerd labels: dedicated-for: experiment machine: architecture: amd64 image: name: coreos type: g1a.8d maxSurge: 1 maxUnavailable: 0 maximum: 1 minimum: 0 systemComponents: allow: false taints: - effect: NoSchedule key: dedicated-for value: experiment volume: size: 50Gi type: storage_premium_perf1 zones: - eu01-3 purpose: production region: RegionOne ================================================ FILE: hack/config/skaffold.yaml ================================================ apiVersion: skaffold/v4beta13 kind: Config metadata: name: cert-manager manifests: kustomize: paths: - hack/config/cert-manager deploy: kubectl: flags: apply: - --server-side - --force-conflicts defaultNamespace: "" hooks: after: - host: command: - /usr/bin/env - bash - -c - | for i in $(seq 1 20); do if [ "$(kubectl get validatingwebhookconfiguration cert-manager-webhook -oyaml 2>/dev/null | yq '.webhooks[].clientConfig.caBundle')" != "null" ] ; then exit 0 fi echo "Waiting until CA has been injected into cert-manager webhook" sleep 5 done exit 1 --- apiVersion: skaffold/v4beta13 kind: Config metadata: name: cert-manager-resources manifests: kustomize: paths: - hack/config/cert-manager/resources deploy: kubectl: flags: apply: - --server-side - --force-conflicts defaultNamespace: "" --- apiVersion: skaffold/v4beta13 kind: Config metadata: name: ingress-nginx manifests: kustomize: paths: - hack/config/ingress-nginx/default deploy: kubectl: flags: apply: - --server-side - --force-conflicts defaultNamespace: "" hooks: before: - host: command: - /usr/bin/env - bash - -c # job template is immutable, delete the old job to prepare for upgrade - kubectl -n ingress-nginx delete job --ignore-not-found ingress-nginx-admission-create ingress-nginx-admission-patch profiles: - name: kind activation: - kubeContext: kind-.* manifests: kustomize: paths: - hack/config/ingress-nginx/kind - name: shoot activation: - kubeContext: .*--sharding.* manifests: kustomize: paths: - hack/config/ingress-nginx/shoot --- apiVersion: skaffold/v4beta13 kind: Config metadata: name: kyverno manifests: kustomize: paths: - hack/config/kyverno deploy: kubectl: flags: apply: - --server-side - --force-conflicts defaultNamespace: "" hooks: after: - host: command: - /usr/bin/env - bash - -c - | kubectl wait --for=condition=Available=true deploy -n kyverno kyverno-admission-controller --timeout=120s kubectl wait --for=create validatingwebhookconfiguration kyverno-policy-validating-webhook-cfg kubectl wait --for=create mutatingwebhookconfiguration kyverno-resource-mutating-webhook-cfg for i in $(seq 1 20); do # create dummy policy with dry-run enabled to test availability of webhook if kubectl create --dry-run=server -f <(yq '.metadata.name |= "test-kyverno"' hack/config/policy/shoot/sharder-scheduling.yaml) ; then exit 0 fi echo "Waiting until kyverno webhook is ready to handle policy creation" sleep 5 done exit 1 --- apiVersion: skaffold/v4beta13 kind: Config metadata: name: policy requires: - configs: - kyverno profiles: - name: shoot activation: - kubeContext: .*--sharding.* manifests: kustomize: paths: - hack/config/policy/shoot deploy: kubectl: flags: apply: - --server-side - --force-conflicts defaultNamespace: "" - name: ci activation: - env: CI=.+ manifests: kustomize: paths: - hack/config/policy/ci deploy: kubectl: flags: apply: - --server-side - --force-conflicts defaultNamespace: "" hooks: after: - host: command: - /usr/bin/env - bash - -c - kubectl wait --for=condition=Ready=true clusterpolicy no-requests-limits --timeout=30s --- apiVersion: skaffold/v4beta13 kind: Config metadata: name: sharder build: artifacts: - image: ghcr.io/timebertt/kubernetes-controller-sharding/sharder ko: dependencies: paths: - go.mod - cmd/**/*.go - pkg/**/*.go main: ./cmd/sharder tagPolicy: inputDigest: {} local: concurrency: 0 manifests: kustomize: paths: - config/default hooks: before: - host: # ensure deepcopy, CRDs, and RBAC are up-to-date command: - make - generate-fast deploy: kubectl: flags: apply: - --server-side - --force-conflicts defaultNamespace: "" profiles: - name: devel activation: - kubeContext: kind-.* - env: DEVEL=true patches: - op: replace path: /manifests/kustomize/paths/0 value: hack/config/sharder/devel --- apiVersion: skaffold/v4beta13 kind: Config metadata: name: checksum-controller build: artifacts: - image: ghcr.io/timebertt/kubernetes-controller-sharding/checksum-controller ko: dependencies: paths: - go.mod - cmd/**/*.go - pkg/**/*.go main: ./cmd/checksum-controller tagPolicy: inputDigest: {} local: concurrency: 0 manifests: kustomize: paths: - hack/config/checksum-controller/controller deploy: kubectl: flags: apply: - --server-side - --force-conflicts defaultNamespace: "" --- apiVersion: skaffold/v4beta13 kind: Config metadata: name: monitoring-crds manifests: kustomize: paths: - hack/config/monitoring/crds deploy: kubectl: flags: apply: - --server-side - --force-conflicts defaultNamespace: "" --- apiVersion: skaffold/v4beta13 kind: Config metadata: name: monitoring requires: - configs: - monitoring-crds manifests: kustomize: paths: - hack/config/monitoring/default - config/monitoring hooks: before: - host: command: - hack/config/monitoring/default/ensure-admin-password.sh deploy: kubectl: flags: apply: - --server-side - --force-conflicts defaultNamespace: "" portForward: - resourceType: service resourceName: grafana namespace: monitoring port: http localPort: 3001 - resourceType: service resourceName: prometheus-k8s namespace: monitoring port: web localPort: 9091 profiles: - name: shoot activation: - kubeContext: .*--sharding.* patches: - op: replace path: /manifests/kustomize/paths/0 value: hack/config/monitoring/shoot --- apiVersion: skaffold/v4beta13 kind: Config metadata: name: profiling profiles: - name: profiling manifests: kustomize: paths: - hack/config/profiling hooks: before: - host: command: - hack/config/profiling/ensure-admin-password.sh deploy: kubectl: flags: apply: - --server-side - --force-conflicts defaultNamespace: "" portForward: - resourceType: service resourceName: parca namespace: parca port: http localPort: 7071 --- apiVersion: skaffold/v4beta13 kind: Config metadata: name: webhosting-operator build: artifacts: - image: ghcr.io/timebertt/kubernetes-controller-sharding/webhosting-operator ko: dependencies: paths: - go.mod - webhosting-operator/go.mod - pkg/**/*.go - webhosting-operator/**/*.go main: ./webhosting-operator/cmd/webhosting-operator tagPolicy: inputDigest: {} local: concurrency: 0 manifests: kustomize: paths: # default configuration: only run operator shards and use external sharding implementation via ControllerRing - webhosting-operator/config/manager/overlays/default - webhosting-operator/config/monitoring/default deploy: kubectl: flags: apply: - --server-side - --force-conflicts defaultNamespace: "" hooks: before: - host: # ensure CRDs and RBAC are up-to-date command: - make - generate-fast-webhosting profiles: - name: devel activation: - kubeContext: kind-.* - env: DEVEL=true patches: - op: replace path: /manifests/kustomize/paths/0 value: webhosting-operator/config/manager/overlays/devel - name: debug activation: - command: debug patches: - op: replace path: /manifests/kustomize/paths/0 value: webhosting-operator/config/manager/overlays/debug - name: non-sharded activation: - env: ENABLE_SHARDING=false patches: - op: replace path: /manifests/kustomize/paths/0 # singleton controller without sharding for comparison value: webhosting-operator/config/manager/overlays/non-sharded - name: non-sharded-devel activation: - env: ENABLE_SHARDING=false - env: DEVEL=true requiresAllActivations: true patches: - op: replace path: /manifests/kustomize/paths/0 value: webhosting-operator/config/manager/overlays/non-sharded-devel # The following profiles are variants of the default and non-sharded profiles for running on the shoot cluster # with dns for websites enabled. - name: shoot activation: - kubeContext: .*--sharding.* patches: - op: replace path: /manifests/kustomize/paths/0 # default configuration: run sharded operator and use external sharding implementation via ControllerRing value: webhosting-operator/config/manager/overlays/shoot/default - op: add path: /manifests/kustomize/paths/- value: webhosting-operator/config/policy - name: shoot-devel activation: - kubeContext: .*--sharding.* - env: DEVEL=true requiresAllActivations: true patches: - op: replace path: /manifests/kustomize/paths/0 # default configuration + devel mode value: webhosting-operator/config/manager/overlays/shoot/devel - name: shoot-non-sharded activation: - kubeContext: .*--sharding.* - env: ENABLE_SHARDING=false requiresAllActivations: true patches: - op: replace path: /manifests/kustomize/paths/0 # singleton controller without sharding for comparison value: webhosting-operator/config/manager/overlays/shoot/non-sharded - name: shoot-non-sharded-devel activation: - kubeContext: .*--sharding.* - env: ENABLE_SHARDING=false - env: DEVEL=true requiresAllActivations: true patches: - op: replace path: /manifests/kustomize/paths/0 # non-sharded configuration + devel mode value: webhosting-operator/config/manager/overlays/shoot/non-sharded-devel --- apiVersion: skaffold/v4beta13 kind: Config metadata: name: experiment profiles: - name: expirement activation: - env: EXPERIMENT_SCENARIO=.+ build: artifacts: - image: ghcr.io/timebertt/kubernetes-controller-sharding/experiment ko: dependencies: paths: - go.mod - webhosting-operator/go.mod - pkg/**/*.go - webhosting-operator/**/*.go main: ./webhosting-operator/cmd/experiment tagPolicy: inputDigest: {} local: concurrency: 0 manifests: kustomize: paths: - webhosting-operator/config/experiment/{{ .EXPERIMENT_SCENARIO }} deploy: kubectl: flags: apply: - --server-side - --force-conflicts defaultNamespace: "" hooks: before: - host: command: - /usr/bin/env - bash - -c - | active_pods="$(kubectl -n experiment get job experiment -ojsonpath='{.status.active}' 2>/dev/null)" if [ "${active_pods:-0}" -gt 0 ] && [ -z "$EXPERIMENT_DELETE_FORCE" ] ; then echo "Experiment is running currently, refusing to delete the job. Set EXPERIMENT_DELETE_FORCE to override." exit 1 fi kubectl -n experiment delete job experiment --ignore-not-found --wait=true - host: command: - /usr/bin/env - bash - -c - | if kubectl get controllerring checksum-controller &>/dev/null || kubectl -n default get deploy checksum-controller &>/dev/null ; then echo "checksum-controller is still running, refusing to run a load test experiment." echo "Ensure a clean load test environment, i.e., run 'make down SKAFFOLD_MODULE=checksum-controller'." exit 1 fi ================================================ FILE: hack/prepare-image-metadata.sh ================================================ #!/usr/bin/env bash # This script generates comma-separated tags and labels for image builds (similar to docker/metadata-action). # It writes its output to the github output variable file or env file. It can only be used in github actions. set -x set -o errexit set -o pipefail set -o nounset build_date="$(date -u +%Y-%m-%dT%H:%M:%SZ)" # revision is the commit sha revision=$GITHUB_SHA # short_ref is the branch name, or the semver git tag short_ref=$GITHUB_REF_NAME # version is the semantic version version=v0.1.0-dev # used if no semver tag has been pushed yet major_version="0" minor_version="1" tags=( "sha-$( echo "$revision" | head -c7 )" ) if [[ $short_ref = main ]] ; then tags+=( latest ) fi if [[ $GITHUB_REF = refs/tags/* && $short_ref =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)([-].*)?([+].*)?$ ]] ; then # triggered for a semver tag, add it as image tag tags+=( "$short_ref" ) # extract version information version=$short_ref major_version=${BASH_REMATCH[1]} minor_version=${BASH_REMATCH[2]} elif [[ "$(git describe --tags --match "v*.*.*" --abbrev=0 2>/dev/null)" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]] ; then # otherwise, find the previous semver tag, extract its information, bump minor/patch, and append -dev major_version=${BASH_REMATCH[1]} minor_version=${BASH_REMATCH[2]} patch_version=${BASH_REMATCH[3]} if [[ $short_ref = release-* ]] ; then (( patch_version++ )) else (( minor_version++ )) fi version=v$major_version.$minor_version.$patch_version-dev fi labels=( org.opencontainers.image.created="$build_date" org.opencontainers.image.licenses="Apache-2.0" org.opencontainers.image.revision="$revision" org.opencontainers.image.source="https://github.com/$GITHUB_REPOSITORY" org.opencontainers.image.url="https://github.com/$GITHUB_REPOSITORY" org.opencontainers.image.version="$version" ) echo "tags=$(IFS=, ; echo "${tags[*]}")" >> "$GITHUB_OUTPUT" echo "labels=$(IFS=, ; echo "${labels[*]}")" >> "$GITHUB_OUTPUT" # calculate ldflags for injecting version information into binaries tree_state="$([[ -z "$(git status --porcelain 2>/dev/null)" ]] && echo clean || echo dirty)" # passing multi-line strings through an action output is difficult, through env vars is easier echo "LDFLAGS<> "$GITHUB_ENV" ================================================ FILE: hack/test-e2e.env ================================================ export GOMEGA_DEFAULT_EVENTUALLY_TIMEOUT=5m export GOMEGA_DEFAULT_EVENTUALLY_POLLING_INTERVAL=500ms export GOMEGA_DEFAULT_CONSISTENTLY_DURATION=10s export GOMEGA_DEFAULT_CONSISTENTLY_POLLING_INTERVAL=500ms ================================================ FILE: hack/test-e2e.sh ================================================ #!/usr/bin/env bash set -o nounset set -o pipefail set -o errexit source "$(dirname "$0")/test-e2e.env" ginkgo run --timeout=1h --poll-progress-after=60s --poll-progress-interval=30s --randomize-all --randomize-suites --keep-going -v --show-node-events "$@" ================================================ FILE: hack/test-integration.env ================================================ export KUBEBUILDER_CONTROLPLANE_START_TIMEOUT=2m export GOMEGA_DEFAULT_EVENTUALLY_TIMEOUT=5s export GOMEGA_DEFAULT_EVENTUALLY_POLLING_INTERVAL=200ms export GOMEGA_DEFAULT_CONSISTENTLY_DURATION=5s export GOMEGA_DEFAULT_CONSISTENTLY_POLLING_INTERVAL=200ms ================================================ FILE: hack/test-integration.sh ================================================ #!/usr/bin/env bash set -o nounset set -o pipefail set -o errexit ENVTEST_K8S_VERSION=${ENVTEST_K8S_VERSION:-"1.33"} # shellcheck disable=SC1090 # --use-env allows overwriting the envtest tools path via the KUBEBUILDER_ASSETS env var source <(setup-envtest use --use-env -p env "${ENVTEST_K8S_VERSION}") echo "Using envtest binaries installed at '$KUBEBUILDER_ASSETS'" source "$(dirname "$0")/test-integration.env" test_flags= if [ -n "${CI:-}" ] ; then # Use Ginkgo timeout in CI to print everything that is buffered in GinkgoWriter. test_flags+=" --ginkgo.timeout=5m" else # We don't want Ginkgo's timeout flag locally because it causes skipping the test cache. timeout_flag=-timeout=5m fi # shellcheck disable=SC2086 go test ${timeout_flag:-} "$@" $test_flags ================================================ FILE: hack/test.sh ================================================ #!/usr/bin/env bash set -o nounset set -o pipefail set -o errexit test_flags= if [ -n "${CI:-}" ] ; then # Use Ginkgo timeout in CI to print everything that is buffered in GinkgoWriter. test_flags+=" --ginkgo.timeout=2m" else # We don't want Ginkgo's timeout flag locally because it causes skipping the test cache. timeout_flag=-timeout=2m fi # shellcheck disable=SC2086 go test -race ${timeout_flag:-} "$@" $test_flags ================================================ FILE: hack/tools.go ================================================ //go:build tools /* Copyright 2023 Tim Ebert. 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. */ package hack import ( _ "github.com/onsi/ginkgo/v2/ginkgo" _ "k8s.io/code-generator" ) ================================================ FILE: hack/tools.mk ================================================ TOOLS_BIN_DIR ?= hack/tools/bin export PATH := $(abspath $(TOOLS_BIN_DIR)):$(PATH) # We use a file per tool and version as an indicator for make whether we need to install the tool or a different version # of the tool (make doesn't rerun the rule if the rule is changed). # Use this "function" to add the version file as a prerequisite for the tool target, e.g.: # $(KUBECTL): $(call tool_version_file,$(KUBECTL),$(KUBECTL_VERSION)) tool_version_file = $(TOOLS_BIN_DIR)/.version_$(subst $(TOOLS_BIN_DIR)/,,$(1))_$(2) # Use this "function" to get the version of a go module from go.mod, e.g.: # GINKGO_VERSION ?= $(call version_gomod,github.com/onsi/ginkgo/v2) version_gomod = $(shell go list -f '{{ .Version }}' -m $(1)) # This target cleans up any previous version files for the given tool and creates the given version file. # This way, we can generically determine, which version was installed without calling each and every binary explicitly. $(TOOLS_BIN_DIR)/.version_%: @version_file=$@; rm -f $${version_file%_*}* @touch $@ CONTROLLER_GEN := $(TOOLS_BIN_DIR)/controller-gen # renovate: datasource=github-releases depName=kubernetes-sigs/controller-tools CONTROLLER_GEN_VERSION ?= v0.19.0 $(CONTROLLER_GEN): $(call tool_version_file,$(CONTROLLER_GEN),$(CONTROLLER_GEN_VERSION)) GOBIN=$(abspath $(TOOLS_BIN_DIR)) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_GEN_VERSION) GINKGO := $(TOOLS_BIN_DIR)/ginkgo GINKGO_VERSION ?= $(call version_gomod,github.com/onsi/ginkgo/v2) $(GINKGO): $(call tool_version_file,$(GINKGO),$(GINKGO_VERSION)) go build -o $(GINKGO) github.com/onsi/ginkgo/v2/ginkgo GOLANGCI_LINT := $(TOOLS_BIN_DIR)/golangci-lint # renovate: datasource=github-releases depName=golangci/golangci-lint GOLANGCI_LINT_VERSION ?= v2.8.0 $(GOLANGCI_LINT): $(call tool_version_file,$(GOLANGCI_LINT),$(GOLANGCI_LINT_VERSION)) curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(TOOLS_BIN_DIR) $(GOLANGCI_LINT_VERSION) KIND := $(TOOLS_BIN_DIR)/kind # renovate: datasource=github-releases depName=kubernetes-sigs/kind KIND_VERSION ?= v0.30.0 $(KIND): $(call tool_version_file,$(KIND),$(KIND_VERSION)) curl -Lo $(KIND) https://kind.sigs.k8s.io/dl/$(KIND_VERSION)/kind-$(shell uname -s | tr '[:upper:]' '[:lower:]')-$(shell uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') chmod +x $(KIND) KO := $(TOOLS_BIN_DIR)/ko # renovate: datasource=github-releases depName=ko-build/ko KO_VERSION ?= v0.18.1 $(KO): $(call tool_version_file,$(KO),$(KO_VERSION)) GOBIN=$(abspath $(TOOLS_BIN_DIR)) go install github.com/google/ko@$(KO_VERSION) KUBECTL := $(TOOLS_BIN_DIR)/kubectl # renovate: datasource=github-releases depName=kubectl packageName=kubernetes/kubernetes KUBECTL_VERSION ?= v1.34.4 $(KUBECTL): $(call tool_version_file,$(KUBECTL),$(KUBECTL_VERSION)) curl -Lo $(KUBECTL) https://dl.k8s.io/release/$(KUBECTL_VERSION)/bin/$(shell uname -s | tr '[:upper:]' '[:lower:]')/$(shell uname -m | sed 's/x86_64/amd64/')/kubectl chmod +x $(KUBECTL) SETUP_ENVTEST := $(TOOLS_BIN_DIR)/setup-envtest CONTROLLER_RUNTIME_VERSION ?= $(call version_gomod,sigs.k8s.io/controller-runtime) $(SETUP_ENVTEST): $(call tool_version_file,$(SETUP_ENVTEST),$(CONTROLLER_RUNTIME_VERSION)) curl -Lo $(SETUP_ENVTEST) https://github.com/kubernetes-sigs/controller-runtime/releases/download/$(CONTROLLER_RUNTIME_VERSION)/setup-envtest-$(shell uname -s | tr '[:upper:]' '[:lower:]')-$(shell uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') chmod +x $(SETUP_ENVTEST) SKAFFOLD := $(TOOLS_BIN_DIR)/skaffold # renovate: datasource=github-releases depName=GoogleContainerTools/skaffold SKAFFOLD_VERSION ?= v2.17.1 $(SKAFFOLD): $(call tool_version_file,$(SKAFFOLD),$(SKAFFOLD_VERSION)) curl -Lo $(SKAFFOLD) https://storage.googleapis.com/skaffold/releases/$(SKAFFOLD_VERSION)/skaffold-$(shell uname -s | tr '[:upper:]' '[:lower:]')-$(shell uname -m | sed 's/x86_64/amd64/') chmod +x $(SKAFFOLD) VGOPATH := $(TOOLS_BIN_DIR)/vgopath # renovate: datasource=github-releases depName=ironcore-dev/vgopath VGOPATH_VERSION ?= v0.1.10 $(VGOPATH): $(call tool_version_file,$(VGOPATH),$(VGOPATH_VERSION)) GOBIN=$(abspath $(TOOLS_BIN_DIR)) go install github.com/ironcore-dev/vgopath@$(VGOPATH_VERSION) YQ := $(TOOLS_BIN_DIR)/yq # renovate: datasource=github-releases depName=mikefarah/yq YQ_VERSION ?= v4.52.2 $(YQ): $(call tool_version_file,$(YQ),$(YQ_VERSION)) curl -Lo $(YQ) https://github.com/mikefarah/yq/releases/download/$(YQ_VERSION)/yq_$(shell uname -s | tr '[:upper:]' '[:lower:]')_$(shell uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') chmod +x $(YQ) ================================================ FILE: hack/update-codegen.sh ================================================ #!/usr/bin/env bash # Copyright 2023 Tim Ebert. # # 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. set -o errexit set -o nounset set -o pipefail SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" # fetch code-generator module to execute the scripts from the modcache (we don't vendor here) CODE_GENERATOR_DIR="$(go list -m -tags tools -f '{{ .Dir }}' k8s.io/code-generator)" source "${CODE_GENERATOR_DIR}"/kube_codegen.sh # setup virtual GOPATH # k8s.io/code-generator does not work outside GOPATH, see https://github.com/kubernetes/kubernetes/issues/86753. source "$SCRIPT_DIR"/vgopath-setup.sh # We need to explicitly pass GO111MODULE=off to k8s.io/code-generator as it is significantly slower otherwise, # see https://github.com/kubernetes/code-generator/issues/100. export GO111MODULE=off # sharder config API sharder_config_group() { echo "Generating sharder config API group" kube::codegen::gen_helpers \ --boilerplate "${SCRIPT_DIR}/boilerplate.go.txt" \ "${SCRIPT_DIR}/../pkg/apis" } webhosting_config_group() { echo "Generating webhosting-operator config API group" kube::codegen::gen_helpers \ --boilerplate "${SCRIPT_DIR}/boilerplate.go.txt" \ "${SCRIPT_DIR}/../webhosting-operator/pkg/apis" } sharder_config_group webhosting_config_group ================================================ FILE: hack/vgopath-setup.sh ================================================ # Ensure that if GOPATH is set, the GOPATH/{bin,pkg} directory exists. This might not be the case in CI. # As we will create a symlink against the bin folder we need to make sure that the bin directory is # present in the GOPATH. if [ -n "${GOPATH:-}" ] && [ ! -d "$GOPATH/bin" ]; then mkdir -p "$GOPATH/bin"; fi if [ -n "${GOPATH:-}" ] && [ ! -d "$GOPATH/pkg" ]; then mkdir -p "$GOPATH/pkg"; fi VIRTUAL_GOPATH="$(mktemp -d)" trap 'rm -rf "$VIRTUAL_GOPATH"' EXIT # Setup virtual GOPATH go mod download && vgopath -o "$VIRTUAL_GOPATH" export GOPATH="$VIRTUAL_GOPATH" ================================================ FILE: pkg/apis/config/doc.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ // +groupName=config.sharding.timebertt.dev package config // import "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/config" ================================================ FILE: pkg/apis/config/v1alpha1/defaults.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package v1alpha1 import ( "time" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/leaderelection/resourcelock" componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1" "k8s.io/utils/ptr" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" ) func addDefaultingFuncs(scheme *runtime.Scheme) error { return RegisterDefaults(scheme) } func SetDefaults_SharderConfig(obj *SharderConfig) { if obj.ClientConnection == nil { obj.ClientConnection = &componentbaseconfigv1alpha1.ClientConnectionConfiguration{} } if obj.LeaderElection == nil { obj.LeaderElection = &componentbaseconfigv1alpha1.LeaderElectionConfiguration{} } if obj.Debugging == nil { obj.Debugging = &componentbaseconfigv1alpha1.DebuggingConfiguration{} } if obj.GracefulShutdownTimeout == nil { obj.GracefulShutdownTimeout = &metav1.Duration{Duration: 15 * time.Second} } } func SetDefaults_LeaderElectionConfiguration(obj *componentbaseconfigv1alpha1.LeaderElectionConfiguration) { if obj.ResourceLock == "" { obj.ResourceLock = resourcelock.LeasesResourceLock } componentbaseconfigv1alpha1.RecommendedDefaultLeaderElectionConfiguration(obj) if obj.ResourceName == "" { obj.ResourceName = "sharder" } if obj.ResourceNamespace == "" { obj.ResourceNamespace = shardingv1alpha1.NamespaceSystem } } func SetDefaults_DebuggingConfiguration(obj *componentbaseconfigv1alpha1.DebuggingConfiguration) { componentbaseconfigv1alpha1.RecommendedDebuggingConfiguration(obj) if obj.EnableContentionProfiling == nil { obj.EnableContentionProfiling = ptr.To(false) } } func SetDefaults_HealthEndpoint(obj *HealthEndpoint) { if obj.BindAddress == "" { obj.BindAddress = ":8081" } } func SetDefaults_MetricsEndpoint(obj *MetricsEndpoint) { if obj.BindAddress == "" { obj.BindAddress = ":8080" } } func SetDefaults_Controller(obj *Controller) { if obj.Sharder == nil { obj.Sharder = &SharderController{} } } func SetDefaults_SharderController(obj *SharderController) { if obj.SyncPeriod == nil { obj.SyncPeriod = &metav1.Duration{Duration: 5 * time.Minute} } if obj.ConcurrentMoves == nil { obj.ConcurrentMoves = ptr.To[int32](100) } } func SetDefaults_Webhook(obj *Webhook) { if obj.Server == nil { obj.Server = &WebhookServer{} } if obj.Config == nil { obj.Config = &WebhookConfig{} } } func SetDefaults_WebhookConfig(obj *WebhookConfig) { if obj.ClientConfig == nil { obj.ClientConfig = &admissionregistrationv1.WebhookClientConfig{} } if obj.NamespaceSelector == nil { obj.NamespaceSelector = &metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{{ Key: corev1.LabelMetadataName, Operator: metav1.LabelSelectorOpNotIn, Values: []string{metav1.NamespaceSystem, shardingv1alpha1.NamespaceSystem}, }}, } } } func SetDefaults_WebhookClientConfig(obj *admissionregistrationv1.WebhookClientConfig) { if obj.URL == nil && obj.Service == nil { obj.Service = &admissionregistrationv1.ServiceReference{} } } func SetDefaults_ServiceReference(obj *admissionregistrationv1.ServiceReference) { if obj.Namespace == "" { obj.Namespace = shardingv1alpha1.NamespaceSystem } if obj.Name == "" { obj.Name = "sharder" } } ================================================ FILE: pkg/apis/config/v1alpha1/defaults_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package v1alpha1_test import ( "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1" "k8s.io/utils/ptr" . "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/config/v1alpha1" ) var _ = Describe("SharderConfig defaulting", func() { var obj *SharderConfig BeforeEach(func() { obj = &SharderConfig{} }) Context("ClientConnectionConfiguration", func() { It("should not set any default values", func() { SetObjectDefaults_SharderConfig(obj) Expect(obj.ClientConnection).To(Equal(&componentbaseconfigv1alpha1.ClientConnectionConfiguration{})) }) }) Context("LeaderElectionConfiguration", func() { It("should set default values", func() { SetObjectDefaults_SharderConfig(obj) Expect(obj.LeaderElection).To(Equal(&componentbaseconfigv1alpha1.LeaderElectionConfiguration{ LeaderElect: ptr.To(true), LeaseDuration: metav1.Duration{Duration: 15 * time.Second}, RenewDeadline: metav1.Duration{Duration: 10 * time.Second}, RetryPeriod: metav1.Duration{Duration: 2 * time.Second}, ResourceLock: "leases", ResourceName: "sharder", ResourceNamespace: "sharding-system", })) }) }) Context("DebuggingConfiguration", func() { It("should set default values", func() { SetObjectDefaults_SharderConfig(obj) Expect(obj.Debugging).To(Equal(&componentbaseconfigv1alpha1.DebuggingConfiguration{ EnableProfiling: ptr.To(true), EnableContentionProfiling: ptr.To(false), })) }) }) Context("manager settings", func() { It("should set default values", func() { SetObjectDefaults_SharderConfig(obj) Expect(obj.Health).To(Equal(HealthEndpoint{ BindAddress: ":8081", })) Expect(obj.Metrics).To(Equal(MetricsEndpoint{ BindAddress: ":8080", })) Expect(obj.GracefulShutdownTimeout).To(Equal(&metav1.Duration{Duration: 15 * time.Second})) }) }) Context("controller config", func() { It("should set default values", func() { SetObjectDefaults_SharderConfig(obj) Expect(obj.Controller).To(Equal(Controller{ Sharder: &SharderController{ SyncPeriod: &metav1.Duration{Duration: 5 * time.Minute}, ConcurrentMoves: ptr.To[int32](100), }, })) }) }) Context("webhook config", func() { It("should set default values", func() { SetObjectDefaults_SharderConfig(obj) Expect(obj.Webhook).To(Equal(Webhook{ Server: &WebhookServer{}, Config: &WebhookConfig{ ClientConfig: &admissionregistrationv1.WebhookClientConfig{ Service: &admissionregistrationv1.ServiceReference{ Namespace: "sharding-system", Name: "sharder", }, }, NamespaceSelector: &metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{{ Key: "kubernetes.io/metadata.name", Operator: "NotIn", Values: []string{"kube-system", "sharding-system"}, }}, }, }, })) }) }) }) ================================================ FILE: pkg/apis/config/v1alpha1/doc.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ // +k8s:defaulter-gen=TypeMeta package v1alpha1 // import "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/config/v1alpha1" ================================================ FILE: pkg/apis/config/v1alpha1/register.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ // Package v1alpha1 contains API Schema definitions for the config v1alpha1 API group // +kubebuilder:object:generate=true // +groupName=config.sharding.timebertt.dev package v1alpha1 import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) // GroupName is the group name used in this package. const GroupName = "config.sharding.timebertt.dev" // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} var ( // SchemeBuilder is a new Scheme Builder which registers our API. SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, addDefaultingFuncs) // AddToScheme is a reference to the Scheme Builder's AddToScheme function. AddToScheme = SchemeBuilder.AddToScheme ) // Adds the list of known types to the given scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &SharderConfig{}, ) return nil } ================================================ FILE: pkg/apis/config/v1alpha1/types.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package v1alpha1 import ( admissionregistrationv1 "k8s.io/api/admissionregistration/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1" ) //+kubebuilder:object:root=true // SharderConfig is the configuration object for the sharder component. type SharderConfig struct { metav1.TypeMeta `json:",inline"` // ClientConnection holds configuration for the kubernetes API clients. // +optional ClientConnection *componentbaseconfigv1alpha1.ClientConnectionConfiguration `json:"clientConnection,omitempty"` // LeaderElection is the LeaderElection config to be used when configuring // the manager.Manager leader election // +optional LeaderElection *componentbaseconfigv1alpha1.LeaderElectionConfiguration `json:"leaderElection,omitempty"` // Debugging holds configuration for Debugging related features. // +optional Debugging *componentbaseconfigv1alpha1.DebuggingConfiguration `json:"debugging,omitempty"` // Health contains the controller health configuration Health HealthEndpoint `json:"health"` // Metrics contains the controller metrics configuration Metrics MetricsEndpoint `json:"metrics"` // Controller configures the sharder's controllers. Controller Controller `json:"controller"` // Webhook configures webhooks and the webhook server. Webhook Webhook `json:"webhook"` // GracefulShutdownTimeout is the duration given to runnable to stop before the manager actually returns on stop. // To disable graceful shutdown, set it to 0s. // To use graceful shutdown without timeout, set to a negative duration, e.G. -1s. // The graceful shutdown is skipped for safety reasons in case the leader election lease is lost. // Defaults to 15s GracefulShutdownTimeout *metav1.Duration `json:"gracefulShutDown,omitempty"` } // HealthEndpoint defines the health configs. type HealthEndpoint struct { // BindAddress is the TCP address that the controller should bind to // for serving health probes // It can be set to "0" to disable serving the health probe. // Defaults to :8081 // +optional BindAddress string `json:"bindAddress,omitempty"` } // MetricsEndpoint defines the metrics configs. type MetricsEndpoint struct { // 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. // Defaults to :8080 // +optional BindAddress string `json:"bindAddress,omitempty"` } // Controller configures the sharder's controllers. type Controller struct { // Sharder configures the sharder controller. // +optional Sharder *SharderController `json:"sharder,omitempty"` } // SharderController configures the sharder controller. type SharderController struct { // SyncPeriod configures how often a periodic resync of all object assignments in a ring is performed. // Defaults to 5m // +optional SyncPeriod *metav1.Duration `json:"syncPeriod,omitempty"` // ConcurrentMoves configures how many objects of the same ControllerRing are moved (or drained) concurrently at // maximum. // Defaults to 100 // +optional ConcurrentMoves *int32 `json:"concurrentMoves,omitempty"` } // Webhook configures webhooks and the webhook server. type Webhook struct { // Server configures the sharder's webhook server. // +optional Server *WebhookServer `json:"server,omitempty"` // Config configures the sharder's MutatingWebhookConfiguration objects. // +optional Config *WebhookConfig `json:"config,omitempty"` } // WebhookServer configures the webhook server. type WebhookServer struct { // CertDir is the directory that contains the server key and certificate. // Defaults to /tmp/k8s-webhook-server/serving-certs // +optional CertDir *string `json:"certDir,omitempty"` // CertName is the server certificate name. // Defaults to tls.crt // +optional CertName *string `json:"certName,omitempty"` // KeyName is the server key name. // Defaults to tls.key // +optional KeyName *string `json:"keyName,omitempty"` } // WebhookConfig configures the sharder's MutatingWebhookConfiguration objects. type WebhookConfig struct { // Annotations are additional annotations that should be added to all webhook configs. // +optional Annotations map[string]string `json:"annotations,omitempty"` // ClientConfig configures the webhook configs' target. // Defaults to a service reference to sharding-system/sharder. // +optional ClientConfig *admissionregistrationv1.WebhookClientConfig `json:"clientConfig,omitempty"` // NamespaceSelector overwrites the webhook configs' default namespaceSelector. // Note: changing/unsetting this selector will not remove labels from objects in namespaces that were previously // included. // Defaults to excluding the kube-system and sharding-system namespaces // +optional NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty"` } ================================================ FILE: pkg/apis/config/v1alpha1/v1alpha1_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package v1alpha1_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestV1alpha1(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Sharder Config API V1alpha1 Suite") } ================================================ FILE: pkg/apis/config/v1alpha1/zz_generated.deepcopy.go ================================================ //go:build !ignore_autogenerated /* Copyright 2023 Tim Ebert. 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. */ // Code generated by controller-gen. DO NOT EDIT. package v1alpha1 import ( admissionregistrationv1 "k8s.io/api/admissionregistration/v1" "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" configv1alpha1 "k8s.io/component-base/config/v1alpha1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Controller) DeepCopyInto(out *Controller) { *out = *in if in.Sharder != nil { in, out := &in.Sharder, &out.Sharder *out = new(SharderController) (*in).DeepCopyInto(*out) } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Controller. func (in *Controller) DeepCopy() *Controller { if in == nil { return nil } out := new(Controller) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HealthEndpoint) DeepCopyInto(out *HealthEndpoint) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HealthEndpoint. func (in *HealthEndpoint) DeepCopy() *HealthEndpoint { if in == nil { return nil } out := new(HealthEndpoint) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MetricsEndpoint) DeepCopyInto(out *MetricsEndpoint) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricsEndpoint. func (in *MetricsEndpoint) DeepCopy() *MetricsEndpoint { if in == nil { return nil } out := new(MetricsEndpoint) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SharderConfig) DeepCopyInto(out *SharderConfig) { *out = *in out.TypeMeta = in.TypeMeta if in.ClientConnection != nil { in, out := &in.ClientConnection, &out.ClientConnection *out = new(configv1alpha1.ClientConnectionConfiguration) **out = **in } if in.LeaderElection != nil { in, out := &in.LeaderElection, &out.LeaderElection *out = new(configv1alpha1.LeaderElectionConfiguration) (*in).DeepCopyInto(*out) } if in.Debugging != nil { in, out := &in.Debugging, &out.Debugging *out = new(configv1alpha1.DebuggingConfiguration) (*in).DeepCopyInto(*out) } out.Health = in.Health out.Metrics = in.Metrics in.Controller.DeepCopyInto(&out.Controller) in.Webhook.DeepCopyInto(&out.Webhook) if in.GracefulShutdownTimeout != nil { in, out := &in.GracefulShutdownTimeout, &out.GracefulShutdownTimeout *out = new(v1.Duration) **out = **in } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SharderConfig. func (in *SharderConfig) DeepCopy() *SharderConfig { if in == nil { return nil } out := new(SharderConfig) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *SharderConfig) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SharderController) DeepCopyInto(out *SharderController) { *out = *in if in.SyncPeriod != nil { in, out := &in.SyncPeriod, &out.SyncPeriod *out = new(v1.Duration) **out = **in } if in.ConcurrentMoves != nil { in, out := &in.ConcurrentMoves, &out.ConcurrentMoves *out = new(int32) **out = **in } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SharderController. func (in *SharderController) DeepCopy() *SharderController { if in == nil { return nil } out := new(SharderController) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Webhook) DeepCopyInto(out *Webhook) { *out = *in if in.Server != nil { in, out := &in.Server, &out.Server *out = new(WebhookServer) (*in).DeepCopyInto(*out) } if in.Config != nil { in, out := &in.Config, &out.Config *out = new(WebhookConfig) (*in).DeepCopyInto(*out) } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Webhook. func (in *Webhook) DeepCopy() *Webhook { if in == nil { return nil } out := new(Webhook) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WebhookConfig) DeepCopyInto(out *WebhookConfig) { *out = *in if in.Annotations != nil { in, out := &in.Annotations, &out.Annotations *out = make(map[string]string, len(*in)) for key, val := range *in { (*out)[key] = val } } if in.ClientConfig != nil { in, out := &in.ClientConfig, &out.ClientConfig *out = new(admissionregistrationv1.WebhookClientConfig) (*in).DeepCopyInto(*out) } if in.NamespaceSelector != nil { in, out := &in.NamespaceSelector, &out.NamespaceSelector *out = new(v1.LabelSelector) (*in).DeepCopyInto(*out) } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookConfig. func (in *WebhookConfig) DeepCopy() *WebhookConfig { if in == nil { return nil } out := new(WebhookConfig) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WebhookServer) DeepCopyInto(out *WebhookServer) { *out = *in if in.CertDir != nil { in, out := &in.CertDir, &out.CertDir *out = new(string) **out = **in } if in.CertName != nil { in, out := &in.CertName, &out.CertName *out = new(string) **out = **in } if in.KeyName != nil { in, out := &in.KeyName, &out.KeyName *out = new(string) **out = **in } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookServer. func (in *WebhookServer) DeepCopy() *WebhookServer { if in == nil { return nil } out := new(WebhookServer) in.DeepCopyInto(out) return out } ================================================ FILE: pkg/apis/config/v1alpha1/zz_generated.defaults.go ================================================ //go:build !ignore_autogenerated // +build !ignore_autogenerated /* Copyright 2023 Tim Ebert. 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. */ // Code generated by defaulter-gen. DO NOT EDIT. package v1alpha1 import ( runtime "k8s.io/apimachinery/pkg/runtime" ) // RegisterDefaults adds defaulters functions to the given scheme. // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { scheme.AddTypeDefaultingFunc(&SharderConfig{}, func(obj interface{}) { SetObjectDefaults_SharderConfig(obj.(*SharderConfig)) }) return nil } func SetObjectDefaults_SharderConfig(in *SharderConfig) { SetDefaults_SharderConfig(in) if in.LeaderElection != nil { SetDefaults_LeaderElectionConfiguration(in.LeaderElection) } if in.Debugging != nil { SetDefaults_DebuggingConfiguration(in.Debugging) } SetDefaults_HealthEndpoint(&in.Health) SetDefaults_MetricsEndpoint(&in.Metrics) SetDefaults_Controller(&in.Controller) if in.Controller.Sharder != nil { SetDefaults_SharderController(in.Controller.Sharder) } SetDefaults_Webhook(&in.Webhook) if in.Webhook.Config != nil { SetDefaults_WebhookConfig(in.Webhook.Config) if in.Webhook.Config.ClientConfig != nil { SetDefaults_WebhookClientConfig(in.Webhook.Config.ClientConfig) if in.Webhook.Config.ClientConfig.Service != nil { SetDefaults_ServiceReference(in.Webhook.Config.ClientConfig.Service) } } } } ================================================ FILE: pkg/apis/sharding/doc.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ // +groupName=sharding.timebertt.dev package sharding // import "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding" ================================================ FILE: pkg/apis/sharding/v1alpha1/constants.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package v1alpha1 // This file contains API-related constants for the sharding implementation, e.g. well-known annotations and labels. const ( // NamespaceSystem is the namespace where the sharding system components run. NamespaceSystem = "sharding-system" // AppControllerSharding is the value for the "app.kubernetes.io/name" label used for objects related to controller // sharding. AppControllerSharding = "controller-sharding" // alphaPrefix is a common prefix for all well-known annotations and labels in this API version package. alphaPrefix = "alpha.sharding.timebertt.dev/" // LabelControllerRing is the label on objects that identifies the ControllerRing that the object belongs to. LabelControllerRing = alphaPrefix + "controllerring" // LabelState is the label on Lease objects that reflects the state of a shard for observability purposes. // This label is maintained by the shardlease controller. LabelState = alphaPrefix + "state" // LabelShardPrefix is the qualified prefix for a label on sharded objects that holds the name of the responsible // shard within a ring. Use LabelShard to compute the full label key for a ring. LabelShardPrefix = "shard." + alphaPrefix // LabelDrainPrefix is the qualified prefix for a label on sharded objects that instructs the responsible shard within // a ring to stop reconciling the object and remove both the shard and drain label. Use LabelDrain to compute the full // label key for a ring. LabelDrainPrefix = "drain." + alphaPrefix // IdentityShardLeaseController is the identity that the shardlease controller uses to acquire leases of unavailable // shards. IdentityShardLeaseController = "shardlease-controller" ) // LabelShard returns the label on sharded objects that holds the name of the responsible shard within a ring. func LabelShard(ringName string) string { return LabelShardPrefix + ringName } // LabelDrain returns the label on sharded objects that instructs the responsible shard within a ring to stop reconciling // the object and remove both the shard and drain label. func LabelDrain(ringName string) string { return LabelDrainPrefix + ringName } ================================================ FILE: pkg/apis/sharding/v1alpha1/constants_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package v1alpha1_test import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" ) var _ = Describe("#LabelShard", func() { It("should append the ControllerRing name", func() { Expect(LabelShard("foo")).To(Equal("shard.alpha.sharding.timebertt.dev/foo")) }) }) var _ = Describe("#LabelDrain", func() { It("should append the ControllerRing name", func() { Expect(LabelDrain("foo")).To(Equal("drain.alpha.sharding.timebertt.dev/foo")) }) }) ================================================ FILE: pkg/apis/sharding/v1alpha1/doc.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package v1alpha1 // import "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" ================================================ FILE: pkg/apis/sharding/v1alpha1/register.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ // Package v1alpha1 contains API Schema definitions for the sharding v1alpha1 API group // +kubebuilder:object:generate=true // +groupName=sharding.timebertt.dev package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) // GroupName is the group name used in this package. const GroupName = "sharding.timebertt.dev" // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} var ( // SchemeBuilder is a new Scheme Builder which registers our API. SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) // AddToScheme is a reference to the Scheme Builder's AddToScheme function. AddToScheme = SchemeBuilder.AddToScheme ) // Adds the list of known types to the given scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &ControllerRing{}, &ControllerRingList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil } ================================================ FILE: pkg/apis/sharding/v1alpha1/types_controllerring.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" ) //+kubebuilder:object:root=true //+kubebuilder:resource:scope=Cluster //+kubebuilder:subresource:status //+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=`.status.conditions[?(@.type == "Ready")].status` //+kubebuilder:printcolumn:name="Available",type=string,JSONPath=`.status.availableShards` //+kubebuilder:printcolumn:name="Shards",type=string,JSONPath=`.status.shards` //+kubebuilder:printcolumn:name="Age",type="date",JSONPath=`.metadata.creationTimestamp` //+kubebuilder:validation:XValidation:rule="size(self.metadata.name) <= 63",message="ControllerRing name must not be longer than 63 characters" // ControllerRing declares a virtual ring of sharded controller instances. Objects of the specified resources are // distributed across shards of this ring. Objects in all namespaces are considered unless a namespaceSelector is // specified. type ControllerRing struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec contains the specification of the desired behavior of the ControllerRing. // +optional Spec ControllerRingSpec `json:"spec,omitempty"` // Status contains the most recently observed status of the ControllerRing. // +optional Status ControllerRingStatus `json:"status,omitempty"` } //+kubebuilder:object:root=true // ControllerRingList contains a list of ControllerRings. type ControllerRingList struct { metav1.TypeMeta `json:",inline"` // Standard list metadata. // +optional metav1.ListMeta `json:"metadata,omitempty"` // Items is the list of ControllerRings. Items []ControllerRing `json:"items"` } // ControllerRingSpec defines the desired state of a ControllerRing. type ControllerRingSpec struct { // Resources specifies the list of resources that are distributed across shards in this ControllerRing. // +optional // +listType=map // +listMapKey=group // +listMapKey=resource Resources []RingResource `json:"resources,omitempty"` // NamespaceSelector overwrites the webhook configs' namespaceSelector. // If set, this selector should exclude the kube-system and sharding-system namespaces. // If omitted, the default namespaceSelector from the SharderConfig is used. // Note: changing/unsetting this selector will not remove labels from objects in namespaces that were previously // included. // +optional NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty"` } // RingResource specifies a resource along with controlled resources that is distributed across shards in a ring. type RingResource struct { // GroupResource specifies the resource that is distributed across shards in a ring. // This resource is the controller's main resource, i.e., the resource of which it updates the object status. metav1.GroupResource `json:",inline"` // ControlledResources are additional resources that are distributed across shards in the ControllerRing. // These resources are controlled by the controller's main resource, i.e., they have an owner reference with // controller=true back to the GroupResource of this RingResource. // Typically, the controller also watches objects of this resource and enqueues the owning object (of the main // resource) whenever the status of a controlled object changes. // +optional // +listType=map // +listMapKey=group // +listMapKey=resource ControlledResources []metav1.GroupResource `json:"controlledResources,omitempty"` } const ( // ControllerRingReady is the condition type for the "Ready" condition on ControllerRings. ControllerRingReady = "Ready" ) // ControllerRingStatus defines the observed state of a ControllerRing. type ControllerRingStatus struct { // The generation observed by the ControllerRing controller. // +optional ObservedGeneration int64 `json:"observedGeneration,omitempty"` // Shards is the total number of shards of this ring. Shards int32 `json:"shards"` // AvailableShards is the total number of available shards of this ring. AvailableShards int32 `json:"availableShards"` // Conditions represents the observations of a foo's current state. // Known .status.conditions.type are: "Available", "Progressing", and "Degraded" // +listType=map // +listMapKey=type // +optional Conditions []metav1.Condition `json:"conditions,omitempty"` } // LeaseSelector returns a label selector for selecting shard Lease objects belonging to this ControllerRing. func (c *ControllerRing) LeaseSelector() labels.Selector { return labels.SelectorFromSet(labels.Set{LabelControllerRing: c.Name}) } // LabelShard returns the label on sharded objects that holds the name of the responsible shard within this ControllerRing. func (c *ControllerRing) LabelShard() string { return LabelShard(c.Name) } // LabelDrain returns the label on sharded objects that instructs the responsible shard within this ControllerRing to stop // reconciling the object and remove both the shard and drain label. func (c *ControllerRing) LabelDrain() string { return LabelDrain(c.Name) } ================================================ FILE: pkg/apis/sharding/v1alpha1/types_controllerring_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package v1alpha1_test import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" . "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" ) var _ = Describe("ControllerRing", func() { var ring *ControllerRing BeforeEach(func() { ring = &ControllerRing{ ObjectMeta: metav1.ObjectMeta{ Name: "operator", }, Spec: ControllerRingSpec{ Resources: []RingResource{{ GroupResource: metav1.GroupResource{ Group: "", Resource: "configmaps", }, ControlledResources: []metav1.GroupResource{{ Group: "", Resource: "secrets", }}, }}, }, } }) Describe("#LeaseSelector", func() { It("should return the correct lease selector", func() { Expect(ring.LeaseSelector().String()).To(Equal("alpha.sharding.timebertt.dev/controllerring=operator")) }) }) Describe("#LabelShard", func() { It("should append the ControllerRing name", func() { Expect(ring.LabelShard()).To(Equal("shard.alpha.sharding.timebertt.dev/operator")) }) }) Describe("#LabelDrain", func() { It("should append the ControllerRing name", func() { Expect(ring.LabelDrain()).To(Equal("drain.alpha.sharding.timebertt.dev/operator")) }) }) }) ================================================ FILE: pkg/apis/sharding/v1alpha1/v1alpha1_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package v1alpha1_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestV1alpha1(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Sharding API V1alpha1 Suite") } ================================================ FILE: pkg/apis/sharding/v1alpha1/zz_generated.deepcopy.go ================================================ //go:build !ignore_autogenerated /* Copyright 2023 Tim Ebert. 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. */ // Code generated by controller-gen. DO NOT EDIT. package v1alpha1 import ( "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ControllerRing) DeepCopyInto(out *ControllerRing) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) in.Status.DeepCopyInto(&out.Status) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControllerRing. func (in *ControllerRing) DeepCopy() *ControllerRing { if in == nil { return nil } out := new(ControllerRing) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *ControllerRing) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ControllerRingList) DeepCopyInto(out *ControllerRingList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]ControllerRing, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControllerRingList. func (in *ControllerRingList) DeepCopy() *ControllerRingList { if in == nil { return nil } out := new(ControllerRingList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *ControllerRingList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ControllerRingSpec) DeepCopyInto(out *ControllerRingSpec) { *out = *in if in.Resources != nil { in, out := &in.Resources, &out.Resources *out = make([]RingResource, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } if in.NamespaceSelector != nil { in, out := &in.NamespaceSelector, &out.NamespaceSelector *out = new(v1.LabelSelector) (*in).DeepCopyInto(*out) } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControllerRingSpec. func (in *ControllerRingSpec) DeepCopy() *ControllerRingSpec { if in == nil { return nil } out := new(ControllerRingSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ControllerRingStatus) DeepCopyInto(out *ControllerRingStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions *out = make([]v1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControllerRingStatus. func (in *ControllerRingStatus) DeepCopy() *ControllerRingStatus { if in == nil { return nil } out := new(ControllerRingStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RingResource) DeepCopyInto(out *RingResource) { *out = *in out.GroupResource = in.GroupResource if in.ControlledResources != nil { in, out := &in.ControlledResources, &out.ControlledResources *out = make([]v1.GroupResource, len(*in)) copy(*out, *in) } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RingResource. func (in *RingResource) DeepCopy() *RingResource { if in == nil { return nil } out := new(RingResource) in.DeepCopyInto(out) return out } ================================================ FILE: pkg/controller/add.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package controller import ( "context" "fmt" "sigs.k8s.io/controller-runtime/pkg/manager" configv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/config/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/controller/controllerring" "github.com/timebertt/kubernetes-controller-sharding/pkg/controller/sharder" "github.com/timebertt/kubernetes-controller-sharding/pkg/controller/shardlease" ) // AddToManager adds all controllers to the manager. func AddToManager(ctx context.Context, mgr manager.Manager, config *configv1alpha1.SharderConfig) error { if err := (&controllerring.Reconciler{ Config: config, }).AddToManager(mgr); err != nil { return fmt.Errorf("failed adding controllerring controller: %w", err) } if err := (&sharder.Reconciler{ Config: config, }).AddToManager(mgr); err != nil { return fmt.Errorf("failed adding sharder controller: %w", err) } if err := (&shardlease.Reconciler{}).AddToManager(mgr); err != nil { return fmt.Errorf("failed adding lease controller: %w", err) } return nil } ================================================ FILE: pkg/controller/controllerring/add.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package controllerring import ( coordinationv1 "k8s.io/api/coordination/v1" "k8s.io/utils/clock" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/predicate" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" shardinghandler "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/handler" shardingpredicate "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/predicate" ) // ControllerName is the name of this controller. const ControllerName = "controllerring" // AddToManager adds Reconciler to the given manager. func (r *Reconciler) AddToManager(mgr manager.Manager) error { if r.Client == nil { r.Client = client.WithFieldOwner(mgr.GetClient(), ControllerName+"-controller") } if r.Recorder == nil { r.Recorder = mgr.GetEventRecorderFor(ControllerName + "-controller") } if r.Clock == nil { r.Clock = clock.RealClock{} } return builder.ControllerManagedBy(mgr). Named(ControllerName). For(&shardingv1alpha1.ControllerRing{}, builder.WithPredicates(shardingpredicate.ControllerRingCreatedOrUpdated())). Watches( &coordinationv1.Lease{}, handler.EnqueueRequestsFromMapFunc(shardinghandler.MapLeaseToControllerRing), builder.WithPredicates(r.LeasePredicate()), ). WithOptions(controller.Options{ MaxConcurrentReconciles: 5, }). Complete(r) } func (r *Reconciler) LeasePredicate() predicate.Predicate { return predicate.And( shardingpredicate.IsShardLease(), predicate.Or( // react if a shard lease was created or deleted independent of its availability, we want to update // ControllerRing.status.shards predicate.Funcs{ CreateFunc: func(_ event.CreateEvent) bool { return true }, UpdateFunc: func(_ event.UpdateEvent) bool { return false }, DeleteFunc: func(_ event.DeleteEvent) bool { return true }, }, // for update events, only react if the shard's availability changed shardingpredicate.ShardLeaseAvailabilityChanged(r.Clock), ), ) } ================================================ FILE: pkg/controller/controllerring/add_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controllerring_test import ( "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/clock/testing" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" . "github.com/timebertt/kubernetes-controller-sharding/pkg/controller/controllerring" ) var _ = Describe("Reconciler", func() { var r *Reconciler BeforeEach(func() { r = &Reconciler{} }) Describe("#LeasePredicate", func() { var ( p predicate.Predicate obj, objOld *coordinationv1.Lease fakeClock *testing.FakePassiveClock ) BeforeEach(func() { fakeClock = testing.NewFakePassiveClock(time.Now()) r.Clock = fakeClock p = r.LeasePredicate() obj = &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: "foo-0", }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To("foo-0"), LeaseDurationSeconds: ptr.To[int32](10), AcquireTime: ptr.To(metav1.NewMicroTime(fakeClock.Now().Add(-5 * time.Minute))), RenewTime: ptr.To(metav1.NewMicroTime(fakeClock.Now().Add(-2 * time.Second))), }, } metav1.SetMetaDataLabel(&obj.ObjectMeta, "alpha.sharding.timebertt.dev/controllerring", "foo") objOld = obj.DeepCopy() }) It("should ignore leases with empty label", func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "alpha.sharding.timebertt.dev/controllerring", "") objOld = obj.DeepCopy() Expect(p.Create(event.CreateEvent{Object: obj})).To(BeFalse()) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeFalse()) }) It("should react on create events", func() { Expect(p.Create(event.CreateEvent{Object: obj})).To(BeTrue()) }) It("should react on delete events", func() { Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeTrue()) }) It("should react when shard state changed to available", func() { objOld.Spec.HolderIdentity = nil Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) }) It("should react when shard state changed to unavailable", func() { obj.Spec.HolderIdentity = nil Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) }) It("should ignore when shard state hasn't changed", func() { Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) obj.Spec.HolderIdentity = nil objOld.Spec.HolderIdentity = nil Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) }) }) }) ================================================ FILE: pkg/controller/controllerring/controllerring_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controllerring_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestControllerRing(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "ControllerRing Controller Suite") } ================================================ FILE: pkg/controller/controllerring/reconciler.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package controllerring import ( "context" "fmt" "maps" "strings" "github.com/go-logr/logr" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" coordinationv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/record" "k8s.io/utils/clock" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" configv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/config/v1alpha1" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/leases" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils" "github.com/timebertt/kubernetes-controller-sharding/pkg/webhook/sharder" ) //+kubebuilder:rbac:groups=sharding.timebertt.dev,resources=controllerrings,verbs=get;list;watch //+kubebuilder:rbac:groups=sharding.timebertt.dev,resources=controllerrings/status,verbs=update;patch //+kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=mutatingwebhookconfigurations,verbs=create;patch //+kubebuilder:rbac:groups="",resources=events,verbs=create;patch // Reconciler reconciles ControllerRings. type Reconciler struct { Client client.Client Recorder record.EventRecorder Clock clock.PassiveClock Config *configv1alpha1.SharderConfig } // Reconcile reconciles a ControllerRing object. func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) { log := logf.FromContext(ctx) controllerRing := &shardingv1alpha1.ControllerRing{} if err := r.Client.Get(ctx, req.NamespacedName, controllerRing); err != nil { if apierrors.IsNotFound(err) { log.V(1).Info("Object is gone, stop reconciling") return reconcile.Result{}, nil } return reconcile.Result{}, fmt.Errorf("error retrieving object from store: %w", err) } before := controllerRing.DeepCopy() // reconcile sharder webhook configs if err := r.reconcileWebhooks(ctx, controllerRing); err != nil { return reconcile.Result{}, r.updateStatusError(ctx, log, fmt.Errorf("error reconciling webhooks for ControllerRing: %w", err), controllerRing, before) } // collect list of shards in the ring leaseList := &coordinationv1.LeaseList{} if err := r.Client.List(ctx, leaseList, client.MatchingLabelsSelector{Selector: controllerRing.LeaseSelector()}); err != nil { return reconcile.Result{}, r.updateStatusError(ctx, log, fmt.Errorf("error listing Leases for ControllerRing: %w", err), controllerRing, before) } shards := leases.ToShards(leaseList.Items, r.Clock.Now()) controllerRing.Status.Shards = int32(len(shards)) // nolint:gosec controllerRing.Status.AvailableShards = int32(len(shards.AvailableShards())) // nolint:gosec // update status if necessary return reconcile.Result{}, r.updateStatusSuccess(ctx, controllerRing, before) } func (r *Reconciler) updateStatusSuccess(ctx context.Context, controllerRing, before *shardingv1alpha1.ControllerRing) error { if err := r.OptionallyUpdateStatus(ctx, controllerRing, before, func(ready *metav1.Condition) { ready.Status = metav1.ConditionTrue ready.Reason = "ReconciliationSucceeded" ready.Message = "ControllerRing was successfully reconciled" }); err != nil { return fmt.Errorf("error updating ControllerRing status: %w", err) } return nil } func (r *Reconciler) updateStatusError(ctx context.Context, log logr.Logger, reconcileError error, controllerRing, before *shardingv1alpha1.ControllerRing) error { message := utils.CapitalizeFirst(reconcileError.Error()) r.Recorder.Event(controllerRing, corev1.EventTypeWarning, "ReconciliationFailed", message) if err := r.OptionallyUpdateStatus(ctx, controllerRing, before, func(ready *metav1.Condition) { ready.Status = metav1.ConditionFalse ready.Reason = "ReconciliationFailed" ready.Message = message }); err != nil { // We will return the underlying error to the controller. If we fail to publish it to the status, make sure to log // it at least. log.Error(err, "Error updating ControllerRing status with error") } return reconcileError } func (r *Reconciler) OptionallyUpdateStatus(ctx context.Context, controllerRing, before *shardingv1alpha1.ControllerRing, mutate func(ready *metav1.Condition)) error { // always update status with the latest observed generation, no matter if reconciliation succeeded or not controllerRing.Status.ObservedGeneration = controllerRing.Generation readyCondition := metav1.Condition{ Type: shardingv1alpha1.ControllerRingReady, ObservedGeneration: controllerRing.Generation, } mutate(&readyCondition) meta.SetStatusCondition(&controllerRing.Status.Conditions, readyCondition) if apiequality.Semantic.DeepEqual(controllerRing.Status, before.Status) { return nil } return r.Client.Status().Update(ctx, controllerRing) } func (r *Reconciler) reconcileWebhooks(ctx context.Context, controllerRing *shardingv1alpha1.ControllerRing) error { webhookConfig, err := r.WebhookConfigForControllerRing(controllerRing) if err != nil { return err } return r.Client.Patch(ctx, webhookConfig, client.Apply) } func (r *Reconciler) WebhookConfigForControllerRing(controllerRing *shardingv1alpha1.ControllerRing) (*admissionregistrationv1.MutatingWebhookConfiguration, error) { webhookConfig := WebhookConfigForControllerRing(controllerRing, r.Config.Webhook.Config) if err := controllerutil.SetControllerReference(controllerRing, webhookConfig, r.Client.Scheme()); err != nil { return nil, fmt.Errorf("error setting controller reference: %w", err) } return webhookConfig, nil } func WebhookConfigForControllerRing(controllerRing *shardingv1alpha1.ControllerRing, config *configv1alpha1.WebhookConfig) *admissionregistrationv1.MutatingWebhookConfiguration { return &admissionregistrationv1.MutatingWebhookConfiguration{ TypeMeta: metav1.TypeMeta{ APIVersion: admissionregistrationv1.SchemeGroupVersion.String(), Kind: "MutatingWebhookConfiguration", }, ObjectMeta: metav1.ObjectMeta{ Name: "controllerring-" + controllerRing.Name, Labels: map[string]string{ "app.kubernetes.io/name": shardingv1alpha1.AppControllerSharding, shardingv1alpha1.LabelControllerRing: controllerRing.Name, }, Annotations: maps.Clone(config.Annotations), }, Webhooks: []admissionregistrationv1.MutatingWebhook{WebhookForControllerRing(controllerRing, config)}, } } func WebhookForControllerRing(controllerRing *shardingv1alpha1.ControllerRing, config *configv1alpha1.WebhookConfig) admissionregistrationv1.MutatingWebhook { webhook := admissionregistrationv1.MutatingWebhook{ Name: "sharder.sharding.timebertt.dev", ClientConfig: *config.ClientConfig.DeepCopy(), NamespaceSelector: config.NamespaceSelector.DeepCopy(), // only process unassigned objects ObjectSelector: &metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{{ Key: controllerRing.LabelShard(), Operator: metav1.LabelSelectorOpDoesNotExist, }}, }, // Choose Ignore to trade immediate assignments for minimal disruption, the sharder controller will assign any // objects that missed the sharder webhook. FailurePolicy: ptr.To(admissionregistrationv1.Ignore), TimeoutSeconds: ptr.To(int32(5)), SideEffects: ptr.To(admissionregistrationv1.SideEffectClassNone), AdmissionReviewVersions: []string{"v1"}, } // overwrite namespaceSelector with ring-specific namespaceSelector if specified if controllerRing.Spec.NamespaceSelector != nil { webhook.NamespaceSelector = controllerRing.Spec.NamespaceSelector.DeepCopy() } // add ring-specific path to webhook client config webhookPath := sharder.WebhookPathForControllerRing(controllerRing) if service := webhook.ClientConfig.Service; service != nil { service.Path = ptr.To(webhookPath) } if url := webhook.ClientConfig.URL; url != nil { // We can't use path.Join on URLs because it will drop one slash from the scheme. // We accept both URLs with and without trailing slashes, so trim it if present to ensure we have only one as the // path separator. *url = strings.TrimSuffix(*url, "/") + webhookPath } // add rules for all ring resources for _, ringResource := range controllerRing.Spec.Resources { webhook.Rules = append(webhook.Rules, RuleForResource(ringResource.GroupResource)) for _, controlledResource := range ringResource.ControlledResources { webhook.Rules = append(webhook.Rules, RuleForResource(controlledResource)) } } return webhook } // RuleForResource returns the sharder's webhook rule for the given resource. func RuleForResource(gr metav1.GroupResource) admissionregistrationv1.RuleWithOperations { return admissionregistrationv1.RuleWithOperations{ Operations: []admissionregistrationv1.OperationType{ admissionregistrationv1.Create, admissionregistrationv1.Update, }, Rule: admissionregistrationv1.Rule{ APIGroups: []string{gr.Group}, APIVersions: []string{"*"}, Resources: []string{gr.Resource}, Scope: ptr.To(admissionregistrationv1.AllScopes), }, } } ================================================ FILE: pkg/controller/controllerring/reconciler_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controllerring_test import ( "context" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gstruct" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" configv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/config/v1alpha1" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" . "github.com/timebertt/kubernetes-controller-sharding/pkg/controller/controllerring" ) var _ = Describe("Reconciler", func() { var ( ctx context.Context fakeClient client.Client r *Reconciler ring *shardingv1alpha1.ControllerRing config *configv1alpha1.SharderConfig ) BeforeEach(func() { ctx = context.Background() scheme := runtime.NewScheme() Expect(shardingv1alpha1.AddToScheme(scheme)).To(Succeed()) Expect(configv1alpha1.AddToScheme(scheme)).To(Succeed()) ring = &shardingv1alpha1.ControllerRing{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", Generation: 1, }, Status: shardingv1alpha1.ControllerRingStatus{ ObservedGeneration: 1, Shards: 0, AvailableShards: 0, Conditions: []metav1.Condition{{ Type: "Ready", Status: metav1.ConditionTrue, ObservedGeneration: 1, }}, }, } config = &configv1alpha1.SharderConfig{} scheme.Default(config) fakeClient = fake.NewClientBuilder(). WithScheme(scheme). WithRuntimeObjects(ring). WithStatusSubresource(&shardingv1alpha1.ControllerRing{}). Build() r = &Reconciler{ Client: fakeClient, Config: config, } }) Describe("#OptionallyUpdateStatus", func() { It("should update status if observed generation is outdated", func() { ring.Generation++ Expect(fakeClient.Update(ctx, ring)).To(Succeed()) Expect(r.OptionallyUpdateStatus(ctx, ring, ring.DeepCopy(), func(ready *metav1.Condition) {})).Should(Succeed()) Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(ring), ring)).Should(Succeed()) Expect(ring.Status.ObservedGeneration).Should(Equal(ring.Generation)) Expect(ring.Status.Conditions[0].ObservedGeneration).Should(Equal(ring.Generation)) }) It("should update status if condition mutated", func() { Expect(r.OptionallyUpdateStatus(ctx, ring, ring.DeepCopy(), func(ready *metav1.Condition) { ready.Status = metav1.ConditionFalse })).Should(Succeed()) Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(ring), ring)).Should(Succeed()) Expect(ring.Status.Conditions).Should(ConsistOf(MatchFields(IgnoreExtras, Fields{ "Type": Equal("Ready"), "Status": Equal(metav1.ConditionFalse), "ObservedGeneration": Equal(ring.Generation), }))) }) It("should update status if mutated outside the function", func() { before := ring.DeepCopy() ring.Status.AvailableShards = 1 Expect(r.OptionallyUpdateStatus(ctx, ring, before, func(ready *metav1.Condition) {})).Should(Succeed()) Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(ring), ring)).Should(Succeed()) Expect(ring.Status.AvailableShards).Should(BeEquivalentTo(1)) }) It("should skip updating status if nothing changed", func() { Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(ring), ring)).Should(Succeed()) resourceVersion := ring.ResourceVersion Expect(r.OptionallyUpdateStatus(ctx, ring, ring.DeepCopy(), func(ready *metav1.Condition) { *ready = ring.Status.Conditions[0] })).Should(Succeed()) Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(ring), ring)).Should(Succeed()) Expect(ring.ResourceVersion).Should(Equal(resourceVersion)) }) }) Describe("#WebhookConfigForControllerRing", func() { It("should have the correct metadata", func() { Expect(r.WebhookConfigForControllerRing(ring)).To(PointTo(MatchFields(IgnoreExtras, Fields{ "ObjectMeta": MatchFields(IgnoreExtras, Fields{ "Name": Equal("controllerring-" + ring.Name), "Labels": Equal(map[string]string{ "app.kubernetes.io/name": "controller-sharding", "alpha.sharding.timebertt.dev/controllerring": ring.Name, }), }), }))) }) It("should copy the config's annotations", func() { config.Webhook.Config.Annotations = map[string]string{ "my": "annotation", } Expect(r.WebhookConfigForControllerRing(ring)).To(PointTo( HaveField("ObjectMeta.Annotations", Equal(map[string]string{ "my": "annotation", })), )) }) It("should set the controller reference", func() { ring.UID = "123456" Expect(r.WebhookConfigForControllerRing(ring)).To(PointTo( HaveField("ObjectMeta.OwnerReferences", ConsistOf(metav1.OwnerReference{ APIVersion: "sharding.timebertt.dev/v1alpha1", Kind: "ControllerRing", Name: ring.Name, UID: ring.UID, Controller: ptr.To(true), BlockOwnerDeletion: ptr.To(true), })), )) }) It("should have a single webhook", func() { Expect(r.WebhookConfigForControllerRing(ring)).To(HaveField("Webhooks", HaveLen(1))) }) }) Describe("#WebhookForControllerRing", func() { It("should have the correct settings", func() { Expect(WebhookForControllerRing(ring, config.Webhook.Config)).To(MatchFields(IgnoreExtras, Fields{ "Name": Equal("sharder.sharding.timebertt.dev"), "SideEffects": PointTo(Equal(admissionregistrationv1.SideEffectClassNone)), "AdmissionReviewVersions": ConsistOf("v1"), })) }) It("should have non-problematic failure settings", func() { Expect(WebhookForControllerRing(ring, config.Webhook.Config)).To(MatchFields(IgnoreExtras, Fields{ "FailurePolicy": PointTo(Equal(admissionregistrationv1.Ignore)), "TimeoutSeconds": PointTo(BeEquivalentTo(5)), })) }) Context("client config", func() { It("should use the config's default client config and add the path", func() { Expect(WebhookForControllerRing(ring, config.Webhook.Config).ClientConfig).To(Equal(admissionregistrationv1.WebhookClientConfig{ Service: &admissionregistrationv1.ServiceReference{ Namespace: "sharding-system", Name: "sharder", Path: ptr.To("/webhooks/sharder/controllerring/foo"), }, })) }) It("should use the service client config and add the path", func() { config.Webhook.Config.ClientConfig = &admissionregistrationv1.WebhookClientConfig{ Service: &admissionregistrationv1.ServiceReference{ Namespace: "default", Name: "webhook-service", Port: ptr.To[int32](8080), }, } clientConfig := config.Webhook.Config.ClientConfig.DeepCopy() Expect(WebhookForControllerRing(ring, config.Webhook.Config).ClientConfig).To(Equal(admissionregistrationv1.WebhookClientConfig{ Service: &admissionregistrationv1.ServiceReference{ Namespace: clientConfig.Service.Namespace, Name: clientConfig.Service.Name, Port: clientConfig.Service.Port, Path: ptr.To("/webhooks/sharder/controllerring/foo"), }, })) }) It("should use the URL client config and add the path", func() { config.Webhook.Config.ClientConfig = &admissionregistrationv1.WebhookClientConfig{ URL: ptr.To("https://example.com/webhook"), } Expect(WebhookForControllerRing(ring, config.Webhook.Config).ClientConfig).To(Equal(admissionregistrationv1.WebhookClientConfig{ URL: ptr.To("https://example.com/webhook/webhooks/sharder/controllerring/foo"), })) }) It("should use the URL client config with a trailing slash and add the path", func() { config.Webhook.Config.ClientConfig = &admissionregistrationv1.WebhookClientConfig{ URL: ptr.To("https://example.com/"), } Expect(WebhookForControllerRing(ring, config.Webhook.Config).ClientConfig).To(Equal(admissionregistrationv1.WebhookClientConfig{ URL: ptr.To("https://example.com/webhooks/sharder/controllerring/foo"), })) }) }) Context("namespace selector", func() { It("should use the config's default namespace selector", func() { Expect(WebhookForControllerRing(ring, config.Webhook.Config).NamespaceSelector).To(Equal(&metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{{ Key: corev1.LabelMetadataName, Operator: metav1.LabelSelectorOpNotIn, Values: []string{"kube-system", "sharding-system"}, }}, })) }) It("should use the config's namespace selector", func() { config.Webhook.Config.NamespaceSelector = &metav1.LabelSelector{ MatchLabels: map[string]string{"my": "label"}, } namespaceSelector := config.Webhook.Config.NamespaceSelector.DeepCopy() Expect(WebhookForControllerRing(ring, config.Webhook.Config).NamespaceSelector).To(Equal(namespaceSelector)) }) It("should use the ControllerRing's namespace selector", func() { ring.Spec.NamespaceSelector = &metav1.LabelSelector{ MatchLabels: map[string]string{"my": "label"}, } namespaceSelector := ring.Spec.NamespaceSelector.DeepCopy() Expect(WebhookForControllerRing(ring, config.Webhook.Config).NamespaceSelector).To(Equal(namespaceSelector)) }) }) It("should only select unassigned objects", func() { selector, err := metav1.LabelSelectorAsSelector(WebhookForControllerRing(ring, config.Webhook.Config).ObjectSelector) Expect(err).NotTo(HaveOccurred()) Expect(selector.Matches(labels.Set{})).To(BeTrue()) Expect(selector.Matches(labels.Set{ring.LabelShard(): "shard-1"})).To(BeFalse()) }) It("should add rules for all resources", func() { ring.Spec.Resources = []shardingv1alpha1.RingResource{ { GroupResource: metav1.GroupResource{Group: "", Resource: "configmaps"}, }, { GroupResource: metav1.GroupResource{Group: "apps", Resource: "deployments"}, ControlledResources: []metav1.GroupResource{{Group: "apps", Resource: "replicasets"}}, }, } Expect(WebhookForControllerRing(ring, config.Webhook.Config).Rules).To(ConsistOf( RuleForResource(ring.Spec.Resources[0].GroupResource), RuleForResource(ring.Spec.Resources[1].GroupResource), RuleForResource(ring.Spec.Resources[1].ControlledResources[0]), )) }) }) Describe("#RuleForResource", func() { var gr metav1.GroupResource BeforeEach(func() { gr.Group = "apps" gr.Resource = "deployments" }) It("should act on Create and Update", func() { Expect(RuleForResource(gr).Operations).To(ConsistOf(admissionregistrationv1.Create, admissionregistrationv1.Update)) }) It("should generate a matching rule", func() { Expect(RuleForResource(gr).Rule).To(Equal(admissionregistrationv1.Rule{ APIGroups: []string{"apps"}, APIVersions: []string{"*"}, Resources: []string{"deployments"}, Scope: ptr.To(admissionregistrationv1.AllScopes), })) }) }) }) ================================================ FILE: pkg/controller/sharder/add.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package sharder import ( "time" coordinationv1 "k8s.io/api/coordination/v1" "k8s.io/client-go/util/workqueue" "k8s.io/utils/clock" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" shardinghandler "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/handler" shardingpredicate "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/predicate" ) // ControllerName is the name of this controller. const ControllerName = "sharder" // AddToManager adds Reconciler to the given manager. func (r *Reconciler) AddToManager(mgr manager.Manager) error { if r.Client == nil { r.Client = mgr.GetClient() } if r.Reader == nil { r.Reader = mgr.GetAPIReader() } if r.Clock == nil { r.Clock = clock.RealClock{} } return builder.ControllerManagedBy(mgr). Named(ControllerName). For(&shardingv1alpha1.ControllerRing{}, builder.WithPredicates(shardingpredicate.ControllerRingCreatedOrUpdated())). Watches( &coordinationv1.Lease{}, handler.EnqueueRequestsFromMapFunc(shardinghandler.MapLeaseToControllerRing), builder.WithPredicates(r.LeasePredicate()), ). WithOptions(controller.Options{ MaxConcurrentReconciles: 5, // This custom rate limiter differs from the default in these aspects: // - no overall rate limiting, only per-item rate limiting // - start at 5s base delay, faster retries are probably wasted load on the API server // - cap delay at the configured sync period RateLimiter: workqueue.NewTypedItemExponentialFailureRateLimiter[reconcile.Request](5*time.Second, r.Config.Controller.Sharder.SyncPeriod.Duration), }). Complete(r) } func (r *Reconciler) LeasePredicate() predicate.Predicate { return predicate.And( shardingpredicate.IsShardLease(), shardingpredicate.ShardLeaseAvailabilityChanged(r.Clock), ) } ================================================ FILE: pkg/controller/sharder/reconciler.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package sharder import ( "context" "fmt" "time" "github.com/go-logr/logr" "github.com/hashicorp/go-multierror" coordinationv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/utils/clock" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" configv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/config/v1alpha1" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" shardingmetrics "github.com/timebertt/kubernetes-controller-sharding/pkg/metrics" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/consistenthash" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/key" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/leases" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/ring" utilclient "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/client" utilerrors "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/errors" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/pager" ) //+kubebuilder:rbac:groups=sharding.timebertt.dev,resources=controllerrings,verbs=get;list;watch //+kubebuilder:rbac:groups="",resources=namespaces,verbs=get;list;watch // Note: The sharder requires permissions to list and patch resources listed in ControllerRings. However, the default // sharder role doesn't include permissions for listing/mutating arbitrary resources (which would basically be // cluster-admin access) to adhere to the least privilege principle. // We can't automate permission management in the controllerring controller, because you can't grant permissions you don't // already have. // Hence, users need to grant the sharder permissions for listing/mutating sharded resources explicitly. // Reconciler reconciles ControllerRings. type Reconciler struct { Client client.Client Reader client.Reader Clock clock.PassiveClock Config *configv1alpha1.SharderConfig } // Reconcile reconciles a ControllerRing object. func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) { log := logf.FromContext(ctx) controllerRing := &shardingv1alpha1.ControllerRing{} if err := r.Client.Get(ctx, req.NamespacedName, controllerRing); err != nil { if apierrors.IsNotFound(err) { log.V(1).Info("Object is gone, stop reconciling") return reconcile.Result{}, nil } return reconcile.Result{}, fmt.Errorf("error retrieving object from store: %w", err) } o, err := r.NewOperation(ctx, controllerRing) if err != nil { return reconcile.Result{}, err } log.Info("Starting resync of object assignments for ControllerRing") defer func(start time.Time) { log.Info("Finished resync of object assignments for ControllerRing", "duration", r.Clock.Since(start)) }(r.Clock.Now()) if err := o.ResyncControllerRing(ctx, log); err != nil { return reconcile.Result{}, err } // requeue for periodic resync return reconcile.Result{RequeueAfter: r.Config.Controller.Sharder.SyncPeriod.Duration}, nil } func (r *Reconciler) NewOperation(ctx context.Context, controllerRing *shardingv1alpha1.ControllerRing) (*Operation, error) { // collect list of shards in the ring leaseList := &coordinationv1.LeaseList{} if err := r.Client.List(ctx, leaseList, client.MatchingLabelsSelector{Selector: controllerRing.LeaseSelector()}); err != nil { return nil, fmt.Errorf("error listing Leases for ControllerRing: %w", err) } // get ring and shards from cache hashRing, shards := ring.FromLeases(controllerRing, leaseList, r.Clock.Now()) namespaces, err := r.GetSelectedNamespaces(ctx, controllerRing) if err != nil { return nil, err } return &Operation{ Client: r.Client, Reader: r.Reader, ControllerRing: controllerRing, Namespaces: namespaces, HashRing: hashRing, Shards: shards, Concurrency: int(*r.Config.Controller.Sharder.ConcurrentMoves), }, nil } func (r *Reconciler) GetSelectedNamespaces(ctx context.Context, controllerRing *shardingv1alpha1.ControllerRing) (sets.Set[string], error) { namespaceSelector := r.Config.Webhook.Config.NamespaceSelector if controllerRing.Spec.NamespaceSelector != nil { namespaceSelector = controllerRing.Spec.NamespaceSelector } selector, err := metav1.LabelSelectorAsSelector(namespaceSelector) if err != nil { return nil, reconcile.TerminalError(err) } namespaceList := &corev1.NamespaceList{} if err := r.Client.List(ctx, namespaceList, client.MatchingLabelsSelector{Selector: selector}); err != nil { return nil, fmt.Errorf("error listing selected namespaces for ControllerRing: %w", err) } namespaceSet := sets.New[string]() for _, namespace := range namespaceList.Items { namespaceSet.Insert(namespace.Name) } return namespaceSet, err } type Operation struct { Client client.Client Reader client.Reader ControllerRing *shardingv1alpha1.ControllerRing Namespaces sets.Set[string] HashRing *consistenthash.Ring Shards leases.Shards Concurrency int } type workItem struct { drain bool gr metav1.GroupResource gvk schema.GroupVersionKind key client.ObjectKey resourceVersion string currentShard string } func (o *Operation) ResyncControllerRing(ctx context.Context, log logr.Logger) error { var ( wg wait.Group errs = make(chan error) work = make(chan *workItem, o.Concurrency) ) // Compile all objects that need to be moved or drained, and add them to the queue. // The buffer limit of the queue applies backpressure on the work generator (throttling list paging as needed). wg.Start(func() { o.compileWorkItemsForRing(ctx, work, errs) close(work) }) // read work items from the queue and perform drains/movements with the configured concurrency for i := 0; i < o.Concurrency; i++ { wg.Start(func() { for o.processNextWorkItem(ctx, log, work, errs) { } }) } // wait for all processors, then stop collecting errors go func() { wg.Wait() close(errs) }() // collect all errors and return a combined error if any occurred allErrs := &multierror.Error{ErrorFormat: utilerrors.FormatErrors} for err := range errs { allErrs = multierror.Append(allErrs, err) } return allErrs.ErrorOrNil() } func (o *Operation) compileWorkItemsForRing(ctx context.Context, work chan<- *workItem, errs chan<- error) { // check all ring resources for _, ringResource := range o.ControllerRing.Spec.Resources { errs <- o.compileWorkItemsForResource(ctx, ringResource.GroupResource, false, work) for _, controlledResource := range ringResource.ControlledResources { errs <- o.compileWorkItemsForResource(ctx, controlledResource, true, work) } } } func (o *Operation) compileWorkItemsForResource( ctx context.Context, gr metav1.GroupResource, controlled bool, work chan<- *workItem, ) error { gvks, err := o.Client.RESTMapper().KindsFor(schema.GroupVersionResource{Group: gr.Group, Resource: gr.Resource}) if err != nil { return fmt.Errorf("error determining kinds for resource %q: %w", gr.String(), err) } if len(gvks) == 0 { return fmt.Errorf("no kinds found for resource %q", gr.String()) } var allErrs *multierror.Error list := &metav1.PartialObjectMetadataList{} list.SetGroupVersionKind(gvks[0]) err = pager.New(o.Reader).EachListItemWithAlloc(ctx, list, func(obj client.Object) error { if !o.Namespaces.Has(obj.GetNamespace()) { return nil } if w, err := o.workItemForObject(gr, controlled, obj.(*metav1.PartialObjectMetadata)); err != nil { allErrs = multierror.Append(allErrs, err) } else if w != nil { work <- w } return nil }, // List a recent version from the API server's watch cache by setting resourceVersion=0. This reduces the load on etcd // for ring resyncs. Listing from etcd with quorum read would be a scalability limitation/bottleneck. // If we try to move or drain an object with an old resourceVersion (conflict error), we will retry with exponential // backoff. // This trades retries for smaller impact of periodic resyncs (that don't require any action). utilclient.ResourceVersion("0"), ) if err != nil { allErrs = multierror.Append(allErrs, fmt.Errorf("error listing %s: %w", gr.String(), err)) } return allErrs.ErrorOrNil() } var ( // KeyForObject is an alias for key.ForObject, exposed for testing. KeyForObject = key.ForObject // KeyForController is an alias for key.ForController, exposed for testing. KeyForController = key.ForController ) func (o *Operation) workItemForObject( gr metav1.GroupResource, controlled bool, obj *metav1.PartialObjectMetadata, ) (*workItem, error) { keyFunc := KeyForObject if controlled { keyFunc = KeyForController } hashKey, err := keyFunc(obj) if err != nil { return nil, err } if hashKey == "" { // object should not be assigned return nil, nil } var ( desiredShard = o.HashRing.Hash(hashKey) currentShard = obj.Labels[o.ControllerRing.LabelShard()] ) if desiredShard == "" { // if no shard is available, there's nothing we can do return nil, nil } if desiredShard == currentShard { // object is correctly assigned, nothing to do here return nil, nil } w := &workItem{ gr: gr, gvk: obj.GroupVersionKind(), key: client.ObjectKeyFromObject(obj), resourceVersion: obj.ResourceVersion, currentShard: currentShard, } if currentShard != "" && o.Shards.ByID(currentShard).State.IsAvailable() && !controlled { // If the object should be moved and the current shard is still available, we need to drain it. // We only drain non-controlled objects, the controller's main object is used as a synchronization point for // preventing concurrent reconciliations. w.drain = true } // At this point, the object is either unassigned or the current shard is not available. // We send a (potentially empty) patch to trigger an assignment by the sharder webhook. return w, nil } func (o *Operation) processNextWorkItem( ctx context.Context, log logr.Logger, work <-chan *workItem, errs chan<- error, ) bool { select { case <-ctx.Done(): // stop when context is canceled return false case w, ok := <-work: if !ok { // stop when work queue is closed (all items have been processed) return false } obj := &metav1.PartialObjectMetadata{} obj.SetGroupVersionKind(w.gvk) obj.SetName(w.key.Name) obj.SetNamespace(w.key.Namespace) obj.SetResourceVersion(w.resourceVersion) log = log.WithValues("resource", w.gr, "object", w.key) if w.drain { log.V(1).Info("Draining object from shard", "currentShard", w.currentShard) errs <- o.drainObject(ctx, obj, w.gr) } else { log.V(1).Info("Moving object") errs <- o.moveObject(ctx, obj, w.gr) } } return true } func (o *Operation) drainObject( ctx context.Context, obj *metav1.PartialObjectMetadata, gr metav1.GroupResource, ) error { patch := fmt.Sprintf( // - use optimistic locking by including the object's current resourceVersion // - add drain label; object will go through the sharder webhook when shard removes the drain label, which will // perform the assignment `{"metadata":{"resourceVersion":"%s","labels":{"%s":"true"}}}`, obj.ResourceVersion, o.ControllerRing.LabelDrain(), ) if err := o.Client.Patch(ctx, obj, client.RawPatch(types.MergePatchType, []byte(patch))); err != nil { return fmt.Errorf("error draining %s %q: %w", gr.String(), client.ObjectKeyFromObject(obj), err) } shardingmetrics.DrainsTotal.WithLabelValues( o.ControllerRing.Name, gr.Group, gr.Resource, ).Inc() return nil } func (o *Operation) moveObject( ctx context.Context, obj *metav1.PartialObjectMetadata, gr metav1.GroupResource, ) error { patch := fmt.Sprintf( // - use optimistic locking by including the object's current resourceVersion // - remove shard label // - remove drain label if it is still present, this might happen when trying to drain an object from a shard that // just got unavailable `{"metadata":{"resourceVersion":"%s","labels":{"%s":null,"%s":null}}}`, obj.ResourceVersion, o.ControllerRing.LabelShard(), o.ControllerRing.LabelDrain(), ) if err := o.Client.Patch(ctx, obj, client.RawPatch(types.MergePatchType, []byte(patch))); err != nil { return fmt.Errorf("error moving %s %q: %w", gr.String(), client.ObjectKeyFromObject(obj), err) } shardingmetrics.MovementsTotal.WithLabelValues( o.ControllerRing.Name, gr.Group, gr.Resource, ).Inc() return nil } ================================================ FILE: pkg/controller/sharder/reconciler_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package sharder_test import ( "context" "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" coordinationv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/clock/testing" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" . "sigs.k8s.io/controller-runtime/pkg/envtest/komega" "sigs.k8s.io/controller-runtime/pkg/reconcile" configv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/config/v1alpha1" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" . "github.com/timebertt/kubernetes-controller-sharding/pkg/controller/sharder" utilclient "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/client" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" ) var ( ctx context.Context clock *testing.FakePassiveClock fakeClient client.Client r *Reconciler controllerRing *shardingv1alpha1.ControllerRing config *configv1alpha1.SharderConfig namespace *corev1.Namespace availableShard *coordinationv1.Lease ) var _ = BeforeEach(func() { ctx = context.Background() clock = testing.NewFakePassiveClock(time.Now()) namespace = newNamespace("test") controllerRing = &shardingv1alpha1.ControllerRing{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", }, Spec: shardingv1alpha1.ControllerRingSpec{ Resources: []shardingv1alpha1.RingResource{{ GroupResource: metav1.GroupResource{ Resource: "secrets", }, ControlledResources: []metav1.GroupResource{{ Resource: "configmaps", }}, }}, NamespaceSelector: &metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{{ Key: corev1.LabelMetadataName, Operator: metav1.LabelSelectorOpIn, Values: []string{namespace.Name}, }}, }, }, } availableShard = newLease() fakeClient = fake.NewClientBuilder(). WithScheme(utilclient.SharderScheme). WithObjects(controllerRing, namespace, availableShard). Build() SetClient(fakeClient) config = &configv1alpha1.SharderConfig{} utilclient.SharderScheme.Default(config) r = &Reconciler{ Client: fakeClient, Reader: fakeClient, Clock: clock, Config: config, } }) var _ = Describe("#GetSelectedNamespaces", func() { BeforeEach(func() { Expect(fakeClient.Create(ctx, newNamespace("other"))).To(Succeed()) Expect(fakeClient.Create(ctx, newNamespace(metav1.NamespaceSystem))).To(Succeed()) Expect(fakeClient.Create(ctx, newNamespace(shardingv1alpha1.NamespaceSystem))).To(Succeed()) }) It("should return all matching namespaces", func() { namespaces, err := r.GetSelectedNamespaces(ctx, controllerRing) Expect(err).NotTo(HaveOccurred()) Expect(namespaces.UnsortedList()).To(ConsistOf("test")) }) When("the ControllerRing's namespace selector is unset", func() { BeforeEach(func() { controllerRing.Spec.NamespaceSelector = nil }) It("should use the config's namespace selector", func() { namespaces, err := r.GetSelectedNamespaces(ctx, controllerRing) Expect(err).NotTo(HaveOccurred()) Expect(namespaces.UnsortedList()).To(ConsistOf("test", "other")) }) }) When("the ControllerRing's namespace selector is invalid", func() { BeforeEach(func() { controllerRing.Spec.NamespaceSelector.MatchExpressions[0].Operator = "invalid" }) It("should return a terminal error", func() { Expect(r.GetSelectedNamespaces(ctx, controllerRing)).Error().To(MatchError(reconcile.TerminalError(nil))) }) }) }) var _ = Describe("#NewOperation", func() { var deadShard *coordinationv1.Lease BeforeEach(func() { deadShard = newLease() deadShard.Spec.HolderIdentity = nil Expect(fakeClient.Create(ctx, deadShard)).To(Succeed()) }) It("should collect the shard leases", func() { o, err := r.NewOperation(ctx, controllerRing) Expect(err).NotTo(HaveOccurred()) Expect(o.Shards.IDs()).To(ConsistOf(availableShard.Name, deadShard.Name)) Expect(o.Shards.ByID(availableShard.Name).State.IsAvailable()).To(BeTrue()) Expect(o.Shards.ByID(deadShard.Name).State.IsAvailable()).To(BeFalse()) }) It("should construct a hash ring", func() { o, err := r.NewOperation(ctx, controllerRing) Expect(err).NotTo(HaveOccurred()) Expect(o.HashRing.Hash("foo")).To(Equal(availableShard.Name)) }) It("should collect all matching namespaces", func() { o, err := r.NewOperation(ctx, controllerRing) Expect(err).NotTo(HaveOccurred()) Expect(o.Namespaces.UnsortedList()).To(ConsistOf("test")) }) }) func newNamespace(name string) *corev1.Namespace { return &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{ Name: name, Labels: map[string]string{corev1.LabelMetadataName: name}, }} } func newLease() *coordinationv1.Lease { name := "shard-" + test.RandomSuffix() return &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace.Namespace, Labels: map[string]string{ shardingv1alpha1.LabelControllerRing: controllerRing.Name, }, }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To(name), LeaseDurationSeconds: ptr.To[int32](10), AcquireTime: ptr.To(metav1.NewMicroTime(clock.Now().Add(-5 * time.Minute))), RenewTime: ptr.To(metav1.NewMicroTime(clock.Now().Add(-2 * time.Second))), }, } } ================================================ FILE: pkg/controller/sharder/sharder_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package sharder_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestSharder(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Sharder Controller Suite") } ================================================ FILE: pkg/controller/shardlease/add.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package shardlease import ( coordinationv1 "k8s.io/api/coordination/v1" "k8s.io/client-go/util/workqueue" "k8s.io/utils/clock" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" shardinghandler "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/handler" shardingpredicate "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/predicate" ) // ControllerName is the name of this controller. const ControllerName = "shardlease" // AddToManager adds Reconciler to the given manager. func (r *Reconciler) AddToManager(mgr manager.Manager) error { if r.Client == nil { r.Client = mgr.GetClient() } if r.Clock == nil { r.Clock = clock.RealClock{} } return builder.ControllerManagedBy(mgr). Named(ControllerName). For(&coordinationv1.Lease{}, builder.WithPredicates(r.LeasePredicate())). // enqueue all Leases belonging to a ControllerRing when it is created or the spec is updated Watches( &shardingv1alpha1.ControllerRing{}, handler.EnqueueRequestsFromMapFunc(shardinghandler.MapControllerRingToLeases(r.Client)), builder.WithPredicates(shardingpredicate.ControllerRingCreatedOrUpdated()), ). WithOptions(controller.Options{ MaxConcurrentReconciles: 5, NewQueue: func(controllerName string, rateLimiter workqueue.TypedRateLimiter[reconcile.Request]) workqueue.TypedRateLimitingInterface[reconcile.Request] { return workqueue.NewTypedRateLimitingQueueWithConfig(rateLimiter, workqueue.TypedRateLimitingQueueConfig[reconcile.Request]{ Name: controllerName, Clock: r.Clock, }) }, }). Complete(r) } func (r *Reconciler) LeasePredicate() predicate.Predicate { return predicate.And( shardingpredicate.IsShardLease(), shardingpredicate.ShardLeaseStateChanged(r.Clock), // ignore deletion of shard leases predicate.Funcs{ DeleteFunc: func(_ event.DeleteEvent) bool { return false }, }, ) } ================================================ FILE: pkg/controller/shardlease/add_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package shardlease_test import ( "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/clock/testing" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" . "github.com/timebertt/kubernetes-controller-sharding/pkg/controller/shardlease" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/leases" ) var _ = Describe("Reconciler", func() { var r *Reconciler BeforeEach(func() { r = &Reconciler{} }) Describe("#LeasePredicate", func() { var ( p predicate.Predicate obj, objOld *coordinationv1.Lease fakeClock *testing.FakeClock ) BeforeEach(func() { fakeClock = testing.NewFakeClock(time.Now()) r.Clock = fakeClock p = r.LeasePredicate() obj = &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: "foo-0", }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To("foo-0"), LeaseDurationSeconds: ptr.To[int32](10), AcquireTime: ptr.To(metav1.NewMicroTime(fakeClock.Now().Add(-5 * time.Minute))), RenewTime: ptr.To(metav1.NewMicroTime(fakeClock.Now().Add(-2 * time.Second))), }, } metav1.SetMetaDataLabel(&obj.ObjectMeta, "alpha.sharding.timebertt.dev/controllerring", "foo") objOld = obj.DeepCopy() }) It("should ignore leases with empty label", func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "alpha.sharding.timebertt.dev/controllerring", "") objOld = obj.DeepCopy() Expect(p.Create(event.CreateEvent{Object: obj})).To(BeFalse()) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeFalse()) }) It("should react on create events for unavailable leases", func() { obj.Spec.HolderIdentity = nil Expect(p.Create(event.CreateEvent{Object: obj})).To(BeTrue()) }) It("should react on create events for available leases", func() { Expect(p.Create(event.CreateEvent{Object: obj})).To(BeTrue()) }) It("should react when shard state changed to available", func() { objOld.Spec.HolderIdentity = nil Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) }) It("should react when shard state changed to unavailable", func() { obj.Spec.HolderIdentity = nil Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) }) It("should react when shard state changed while still being available", func() { obj.Spec.RenewTime = ptr.To(metav1.NewMicroTime(fakeClock.Now().Add(-time.Duration(*obj.Spec.LeaseDurationSeconds+1) * time.Second))) Expect(leases.ToState(objOld, fakeClock.Now())).To(Equal(leases.Ready)) Expect(leases.ToState(obj, fakeClock.Now())).To(Equal(leases.Expired)) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) }) It("should ignore when shard state hasn't changed", func() { Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) obj.Spec.HolderIdentity = nil objOld.Spec.HolderIdentity = nil Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) }) It("should ignore delete events", func() { Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeFalse()) }) }) }) ================================================ FILE: pkg/controller/shardlease/reconciler.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package shardlease import ( "context" "fmt" "time" coordinationv1 "k8s.io/api/coordination/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/clock" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/leases" ) //+kubebuilder:rbac:groups=coordination.k8s.io,resources=leases,verbs=get;list;watch;update;patch;delete // Reconciler reconciles shard leases. type Reconciler struct { Client client.Client Clock clock.WithTicker } // Reconcile reconciles a Lease object. func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) { log := logf.FromContext(ctx) lease := &coordinationv1.Lease{} if err := r.Client.Get(ctx, req.NamespacedName, lease); err != nil { if apierrors.IsNotFound(err) { log.V(1).Info("Object is gone, stop reconciling") return reconcile.Result{}, nil } return reconcile.Result{}, fmt.Errorf("error retrieving object from store: %w", err) } controllerRingName := lease.Labels[shardingv1alpha1.LabelControllerRing] if controllerRingName == "" { log.V(1).Info("Ignoring non-shard lease") return reconcile.Result{}, nil } if err := r.Client.Get(ctx, client.ObjectKey{Name: controllerRingName}, &shardingv1alpha1.ControllerRing{}); err != nil { if !apierrors.IsNotFound(err) { return reconcile.Result{}, fmt.Errorf("error checking for existence of ControllerRing: %w", err) } log.V(1).Info("Ignoring shard lease without a corresponding ControllerRing") return reconcile.Result{}, nil } var ( now = r.Clock.Now() previousState = leases.StateFromString(lease.Labels[shardingv1alpha1.LabelState]) shard = leases.ToShard(lease, now) ) log = log.WithValues("state", shard.State, "expirationTime", shard.Times.Expiration, "leaseDuration", shard.Times.LeaseDuration) // maintain state label if previousState != shard.State { patch := client.MergeFromWithOptions(lease.DeepCopy(), client.MergeFromWithOptimisticLock{}) metav1.SetMetaDataLabel(&lease.ObjectMeta, shardingv1alpha1.LabelState, shard.State.String()) if err := r.Client.Patch(ctx, lease, patch); err != nil { return reconcile.Result{}, fmt.Errorf("failed to update state label on lease: %w", err) } } // act on state and determine when to check again var requeueAfter time.Duration switch shard.State { case leases.Ready: if previousState != leases.Ready { log.Info("Shard got available") } requeueAfter = shard.Times.ToExpired case leases.Expired: log.Info("Shard lease has expired") requeueAfter = shard.Times.ToUncertain case leases.Uncertain: log.Info("Shard lease has expired more than leaseDuration ago, trying to acquire shard lease") nowMicro := metav1.NewMicroTime(now) transitions := int32(0) if lease.Spec.LeaseTransitions != nil { transitions = *lease.Spec.LeaseTransitions } lease.Spec.HolderIdentity = ptr.To(shardingv1alpha1.IdentityShardLeaseController) lease.Spec.LeaseDurationSeconds = ptr.To(2 * int32(shard.Times.LeaseDuration.Round(time.Second).Seconds())) lease.Spec.AcquireTime = &nowMicro lease.Spec.RenewTime = &nowMicro lease.Spec.LeaseTransitions = ptr.To(transitions + 1) if err := r.Client.Update(ctx, lease); err != nil { return reconcile.Result{}, fmt.Errorf("error acquiring shard lease: %w", err) } // lease will be enqueued once we observe our previous update via watch // requeue with leaseDuration just to be sure requeueAfter = shard.Times.LeaseDuration case leases.Dead: if previousState != leases.Dead { log.Info("Shard got unavailable") } // garbage collect later requeueAfter = shard.Times.ToOrphaned case leases.Orphaned: // garbage collect and forget orphaned leases return reconcile.Result{}, r.Client.Delete(ctx, lease) default: // Unknown, forget lease return reconcile.Result{}, nil } return reconcile.Result{RequeueAfter: requeueAfter}, nil } ================================================ FILE: pkg/controller/shardlease/shardlease_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package shardlease_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestShardLease(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Shard Lease Controller Suite") } ================================================ FILE: pkg/metrics/add.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package metrics import ( "fmt" "github.com/prometheus/client_golang/prometheus" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/metrics" ) const Namespace = "controller_sharding" // AddToManager adds all metrics exporters for sharding objects to the manager. func AddToManager(mgr manager.Manager) error { if err := ControllerRingExporter.AddToManager(mgr); err != nil { return fmt.Errorf("failed to add ControllerRing exporter: %w", err) } if err := ShardExporter.AddToManager(mgr); err != nil { return fmt.Errorf("failed to add shard exporter: %w", err) } for _, collector := range []prometheus.Collector{ AssignmentsTotal, MovementsTotal, DrainsTotal, RingCalculationsTotal, } { if err := metrics.Registry.Register(collector); err != nil { return fmt.Errorf("failed to add sharding operations metrics: %w", err) } } return nil } ================================================ FILE: pkg/metrics/controllerring.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package metrics import ( "github.com/prometheus/client_golang/prometheus" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/metrics/exporter" ) var ControllerRingExporter = exporter.Exporter[*shardingv1alpha1.ControllerRing, *shardingv1alpha1.ControllerRingList]{ Namespace: Namespace, Subsystem: "controllerring", StaticLabelKeys: []string{"controllerring", "uid"}, GenerateStaticLabelValues: func(controllerRing *shardingv1alpha1.ControllerRing) []string { return []string{controllerRing.Name, string(controllerRing.UID)} }, Metrics: []exporter.Metric[*shardingv1alpha1.ControllerRing]{ { Name: "metadata_generation", Help: "The generation of a ControllerRing", Generate: func(desc *prometheus.Desc, controllerRing *shardingv1alpha1.ControllerRing, staticLabelValues []string, ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( desc, prometheus.GaugeValue, float64(controllerRing.Generation), staticLabelValues..., ) }, }, { Name: "observed_generation", Help: "The latest generation observed by the ControllerRing controller", Generate: func(desc *prometheus.Desc, controllerRing *shardingv1alpha1.ControllerRing, staticLabelValues []string, ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( desc, prometheus.GaugeValue, float64(controllerRing.Status.ObservedGeneration), staticLabelValues..., ) }, }, { Name: "status_shards", Help: "The ControllerRing's total number of shards observed by the ControllerRing controller", Generate: func(desc *prometheus.Desc, controllerRing *shardingv1alpha1.ControllerRing, staticLabelValues []string, ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( desc, prometheus.GaugeValue, float64(controllerRing.Status.Shards), staticLabelValues..., ) }, }, { Name: "status_available_shards", Help: "The ControllerRing's number of available shards observed by the ControllerRing controller", Generate: func(desc *prometheus.Desc, controllerRing *shardingv1alpha1.ControllerRing, staticLabelValues []string, ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( desc, prometheus.GaugeValue, float64(controllerRing.Status.AvailableShards), staticLabelValues..., ) }, }, }, } ================================================ FILE: pkg/metrics/exporter/exporter.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package exporter import ( "context" "fmt" "reflect" "time" "github.com/prometheus/client_golang/prometheus" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/metrics" ) // Exporter is a generic state metrics exporter for a given Kubernetes object kind that can be added to a // controller-runtime manager. type Exporter[O client.Object, L client.ObjectList] struct { client.Reader Namespace, Subsystem string // StaticLabelKeys are added to all Metrics of this Exporter. StaticLabelKeys []string // GenerateStaticLabelValues returns the values for StaticLabelKeys. GenerateStaticLabelValues func(O) []string Metrics []Metric[O] // optional ListOptions []client.ListOption } // Metric describes a single metric and how to generate it per object. type Metric[O client.Object] struct { Name, Help string LabelKeys []string // Generate returns all metric values for the given object. // staticLabelValues is the result of Exporter.GenerateStaticLabelValues and should be added as the first label values // to all metrics. Generate GenerateFunc[O] // desc is completed in Exporter.AddToManager. desc *prometheus.Desc } type GenerateFunc[O client.Object] func(desc *prometheus.Desc, obj O, staticLabelValues []string, ch chan<- prometheus.Metric) // AddToManager adds this exporter to the given manager and completes the Metrics descriptors. func (e *Exporter[O, L]) AddToManager(mgr manager.Manager) error { if e.Reader == nil { e.Reader = mgr.GetCache() } for i, m := range e.Metrics { m.desc = prometheus.NewDesc( prometheus.BuildFQName(e.Namespace, e.Subsystem, m.Name), m.Help, append(e.StaticLabelKeys, m.LabelKeys...), nil, ) e.Metrics[i] = m } return mgr.Add(e) } // NeedLeaderElection tells the manager to run the exporter in all instances. func (e *Exporter[O, L]) NeedLeaderElection() bool { return false } // Start registers this collector in the controller-runtime metrics registry. // When Start runs, caches have already been started, so we are ready to export metrics. func (e *Exporter[O, L]) Start(_ context.Context) error { if err := metrics.Registry.Register(e); err != nil { return fmt.Errorf("failed to register %s exporter: %w", e.Subsystem, err) } return nil } func (e *Exporter[O, L]) Describe(ch chan<- *prometheus.Desc) { for _, m := range e.Metrics { ch <- m.desc } } func (e *Exporter[O, L]) Collect(ch chan<- prometheus.Metric) { ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) defer cancel() list := reflect.New(reflect.TypeOf(*new(L)).Elem()).Interface().(client.ObjectList) if err := e.List(ctx, list, e.ListOptions...); err != nil { e.handleError(ch, fmt.Errorf("error listing %T: %w", list, err)) return } if err := meta.EachListItem(list, func(obj runtime.Object) error { o := obj.(O) staticLabelValues := e.GenerateStaticLabelValues(o) for _, m := range e.Metrics { m.Generate(m.desc, o, staticLabelValues, ch) } return nil }); err != nil { e.handleError(ch, fmt.Errorf("error iterarting %T: %w", list, err)) return } } func (e *Exporter[O, L]) handleError(ch chan<- prometheus.Metric, err error) { for _, m := range e.Metrics { ch <- prometheus.NewInvalidMetric(m.desc, err) } } // GenerateStateSet returns a GenerateFunc that emits stateset metrics: // - it generates one metric per known state // - the value is 1 if getState returns the state, 0 otherwise // - if unknownState is given, a metric with this state label is generated with value 1 if no other state has matched func GenerateStateSet[O client.Object](knownStates []string, unknownState *string, getState func(O) string) GenerateFunc[O] { return func(desc *prometheus.Desc, obj O, staticLabelValues []string, ch chan<- prometheus.Metric) { actual := getState(obj) // generate metrics for all known states known := false for _, state := range knownStates { hasState := actual == state if hasState { known = true } ch <- stateSetMetric(desc, state, hasState, staticLabelValues) } if unknownState != nil { // generate a metric for unknown states ch <- stateSetMetric(desc, *unknownState, !known, staticLabelValues) } } } func stateSetMetric(desc *prometheus.Desc, state string, value bool, staticLabelValues []string) prometheus.Metric { v := 0 if value { v = 1 } return prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(v), append(staticLabelValues, state)...) } // KnownStates converts the given slice of ~string to a slice of strings. func KnownStates[T ~string](s []T) []string { out := make([]string, len(s)) for i := range s { out[i] = string(s[i]) } return out } // KnownStatesStringer converts the given slice of fmt.Stringer to a slice of strings. func KnownStatesStringer[T fmt.Stringer](s []T) []string { out := make([]string, len(s)) for i := range s { out[i] = s[i].String() } return out } ================================================ FILE: pkg/metrics/operations.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package metrics import ( "github.com/prometheus/client_golang/prometheus" ) var ( // AssignmentsTotal is a prometheus counter metric which holds the total number of shard assignments by the sharder // webhook per ControllerRing and GroupResource. // It has a label which refers to the ControllerRing and two labels which refer to the object's GroupResource. AssignmentsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: Namespace, Name: "assignments_total", Help: "Total number of shard assignments by the sharder webhook per ControllerRing and GroupResource", }, []string{"controllerring", "group", "resource"}) // MovementsTotal is a prometheus counter metric which holds the total number of shard movements triggered by the // sharder controller per ControllerRing and GroupResource. // It has a label which refers to the ControllerRing and two labels which refer to the object's GroupResource. MovementsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: Namespace, Name: "movements_total", Help: "Total number of shard movements triggered by the sharder controller per ControllerRing and GroupResource", }, []string{"controllerring", "group", "resource"}) // DrainsTotal is a prometheus counter metric which holds the total number of shard drains triggered by the sharder // controller per ControllerRing and GroupResource. // It has a label which refers to the ControllerRing and two labels which refer to the object's GroupResource. DrainsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: Namespace, Name: "drains_total", Help: "Total number of shard drains triggered by the sharder controller per ControllerRing and GroupResource", }, []string{"controllerring", "group", "resource"}) // RingCalculationsTotal is a prometheus counter metric which holds the total // number of hash ring calculations per ControllerRing. // It has a label which refers to the ControllerRing. RingCalculationsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: Namespace, Name: "ring_calculations_total", Help: "Total number of hash ring calculations per ControllerRing", }, []string{"controllerring"}) ) ================================================ FILE: pkg/metrics/shard.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package metrics import ( "github.com/prometheus/client_golang/prometheus" coordinationv1 "k8s.io/api/coordination/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/metrics/exporter" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/leases" ) var ShardExporter = exporter.Exporter[*coordinationv1.Lease, *coordinationv1.LeaseList]{ Namespace: Namespace, Subsystem: "shard", ListOptions: []client.ListOption{client.HasLabels{shardingv1alpha1.LabelControllerRing}}, StaticLabelKeys: []string{"namespace", "shard", "controllerring"}, GenerateStaticLabelValues: func(lease *coordinationv1.Lease) []string { return []string{lease.Namespace, lease.Name, lease.Labels[shardingv1alpha1.LabelControllerRing]} }, Metrics: []exporter.Metric[*coordinationv1.Lease]{ { Name: "info", Help: "Information about a shard", LabelKeys: []string{"uid"}, Generate: func(desc *prometheus.Desc, lease *coordinationv1.Lease, staticLabelValues []string, ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( desc, prometheus.GaugeValue, 1, append(staticLabelValues, string(lease.UID))..., ) }, }, { Name: "state", Help: "The shard's current state observed by the shardlease controller", LabelKeys: []string{"state"}, Generate: exporter.GenerateStateSet[*coordinationv1.Lease]( exporter.KnownStatesStringer(leases.KnownShardStates), ptr.To(leases.Unknown.String()), func(lease *coordinationv1.Lease) string { return lease.Labels[shardingv1alpha1.LabelState] }, ), }, }, } ================================================ FILE: pkg/shard/controller/builder.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package controller import ( "fmt" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) // Builder can build a sharded reconciler. // Use NewShardedReconciler to create a new Builder. type Builder struct { object client.Object client client.Client controllerRingName string shardName string err error } // NewShardedReconciler returns a new Builder for building a sharded reconciler. // A sharded reconciler needs to handle the shard and drain labels correctly. This builder helps to construct a wrapper // reconciler that takes care of the sharding-related logic and calls the delegate reconciler whenever the shard is // responsible for reconciling an object. func NewShardedReconciler(mgr manager.Manager) *Builder { return (&Builder{}).WithClient(mgr.GetClient()) } // For sets the object kind being reconciled by the reconciler. func (b *Builder) For(object client.Object) *Builder { if b.object != nil { b.err = fmt.Errorf("must not call For() more than once") return b } b.object = object return b } // WithClient overwrites the client to use for reading and patching the controller's objects. // If not set, the manager's client is used. func (b *Builder) WithClient(c client.Client) *Builder { b.client = c return b } // InControllerRing sets the name of the ControllerRing that the shard belongs to. func (b *Builder) InControllerRing(name string) *Builder { b.controllerRingName = name return b } // WithShardName sets the name the shard. func (b *Builder) WithShardName(name string) *Builder { b.shardName = name return b } // MustBuild calls Build and panics if Build returns an error. func (b *Builder) MustBuild(r reconcile.Reconciler) reconcile.Reconciler { result, err := b.Build(r) utilruntime.Must(err) return result } // Build takes the actual reconciler and wraps it in the sharded reconciler. func (b *Builder) Build(r reconcile.Reconciler) (reconcile.Reconciler, error) { if b.err != nil { return nil, b.err } if r == nil { return nil, fmt.Errorf("must provide a non-nil Reconciler") } if b.object == nil { return nil, fmt.Errorf("missing object kind, must call to For()") } if b.client == nil { return nil, fmt.Errorf("missing client") } if b.controllerRingName == "" { return nil, fmt.Errorf("missing ControllerRing name") } if b.shardName == "" { return nil, fmt.Errorf("missing shard name") } return &Reconciler{ Object: b.object, Client: b.client, ControllerRingName: b.controllerRingName, ShardName: b.shardName, Do: r, }, nil } ================================================ FILE: pkg/shard/controller/builder_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controller_test import ( "context" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/reconcile" . "github.com/timebertt/kubernetes-controller-sharding/pkg/shard/controller" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) var _ = Describe("#Builder", func() { var ( mgr fakeManager b *Builder obj *corev1.Pod controllerRingName string shardName string client client.Client r reconcile.Reconciler ) BeforeEach(func() { obj = &corev1.Pod{} controllerRingName = "operator" shardName = "operator-0" client = fakeclient.NewFakeClient() r = reconcile.Func(func(context.Context, reconcile.Request) (reconcile.Result, error) { return reconcile.Result{}, nil }) }) JustBeforeEach(func() { mgr = fakeManager{Client: client} b = NewShardedReconciler(mgr). For(obj). InControllerRing(controllerRingName). WithShardName(shardName) }) Describe("#For", func() { It("should complain about calling For twice", func() { Expect(b.For(obj).Build(r)).Error().To(MatchError("must not call For() more than once")) }) It("should complain about not calling For", func() { b = NewShardedReconciler(mgr). InControllerRing(controllerRingName). WithShardName(shardName) Expect(b.Build(r)).Error().To(MatchError("missing object kind, must call to For()")) }) }) Describe("#WithClient", func() { It("should use the custom client instead of the manager's client", func() { customClient := fakeclient.NewFakeClient() Expect(b.WithClient(customClient).Build(r)).To( HaveField("Client", BeIdenticalTo(customClient)), ) }) It("should complain about missing client", func() { Expect(b.WithClient(nil).Build(r)).Error().To(MatchError("missing client")) }) }) Describe("#InControllerRing", func() { It("should complain about missing ControllerRing name", func() { Expect(b.InControllerRing("").Build(r)).Error().To(MatchError("missing ControllerRing name")) }) }) Describe("#WithShardName", func() { It("should complain about missing shard name", func() { Expect(b.WithShardName("").Build(r)).Error().To(MatchError("missing shard name")) }) }) Describe("#Build", func() { It("should complain about nil reconciler", func() { Expect(b.Build(nil)).Error().To(MatchError("must provide a non-nil Reconciler")) }) It("should correctly set up the Reconciler", func() { shardReconciler, err := b.Build(r) Expect(err).NotTo(HaveOccurred()) reconciler, ok := shardReconciler.(*Reconciler) Expect(ok).To(BeTrue()) Expect(reconciler.Object).To(BeAssignableToTypeOf(obj)) Expect(reconciler.Client).To(BeIdenticalTo(client)) Expect(reconciler.ControllerRingName).To(Equal(controllerRingName)) Expect(reconciler.ShardName).To(Equal(shardName)) Expect(reconciler.Do).To(BeFunc(r)) }) }) Describe("#MustBuild", func() { It("should panic for nil reconciler", func() { Expect(func() { b.MustBuild(nil) }).To(Panic()) }) It("should correctly set up the Reconciler", func() { var shardReconciler reconcile.Reconciler Expect(func() { shardReconciler = b.MustBuild(r) }).NotTo(Panic()) reconciler, ok := shardReconciler.(*Reconciler) Expect(ok).To(BeTrue()) Expect(reconciler.Object).To(BeAssignableToTypeOf(obj)) Expect(reconciler.Client).To(BeIdenticalTo(client)) Expect(reconciler.ControllerRingName).To(Equal(controllerRingName)) Expect(reconciler.ShardName).To(Equal(shardName)) Expect(reconciler.Do).To(BeFunc(r)) }) }) }) type fakeManager struct { manager.Manager Client client.Client } func (f fakeManager) GetClient() client.Client { return f.Client } ================================================ FILE: pkg/shard/controller/controller_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controller_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestController(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Shard Controller Suite") } ================================================ FILE: pkg/shard/controller/predicate.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package controller import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/predicate" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" ) // Predicate sets up a predicate that evaluates to true if // a) the object needs to be drained or // b) the given shard is responsible and all other predicates match. // To support sharding in your controller, use this function to construct a predicate for the object kind given to // `builder.Builder.For` (i.e., the controller's main kind). // It is not needed to use this predicate for secondary watches (e.g., for object kinds given to // `builder.Builder.{Owns,Watches}`) as secondary objects are not drained by the sharder. func Predicate(controllerRingName, shardName string, predicates ...predicate.Predicate) predicate.Predicate { return predicate.Or( // always enqueue if we need to acknowledge the drain operation, other predicates don't matter in this case isDrained(controllerRingName), // or enqueue if we are responsible and all other predicates match predicate.And(isAssigned(controllerRingName, shardName), predicate.And(predicates...)), ) } func isAssigned(controllerRingName, shardName string) predicate.Predicate { return predicate.NewPredicateFuncs(func(object client.Object) bool { return object.GetLabels()[shardingv1alpha1.LabelShard(controllerRingName)] == shardName }) } func isDrained(controllerRingName string) predicate.Predicate { return predicate.NewPredicateFuncs(func(object client.Object) bool { _, drain := object.GetLabels()[shardingv1alpha1.LabelDrain(controllerRingName)] return drain }) } ================================================ FILE: pkg/shard/controller/predicate_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controller_test import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" . "github.com/timebertt/kubernetes-controller-sharding/pkg/shard/controller" ) var _ = Describe("#Predicate", func() { var ( controllerRingName string shardName string mainPredicate, p predicate.Predicate obj, objOld *corev1.Pod ) BeforeEach(func() { controllerRingName = "operator" shardName = "operator-0" obj = &corev1.Pod{} }) JustBeforeEach(func() { p = Predicate(controllerRingName, shardName, mainPredicate) }) When("main predicate returns false", func() { BeforeEach(func() { mainPredicate = predicate.NewPredicateFuncs(func(client.Object) bool { return false }) }) It("should handle drained objects", func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "drain.alpha.sharding.timebertt.dev/"+controllerRingName, "true") objOld = obj.DeepCopy() Expect(p.Create(event.CreateEvent{Object: obj})).To(BeTrue()) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeTrue()) Expect(p.Generic(event.GenericEvent{Object: obj})).To(BeTrue()) }) It("should handle assigned and drained objects", func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "shard.alpha.sharding.timebertt.dev/"+controllerRingName, shardName) metav1.SetMetaDataLabel(&obj.ObjectMeta, "drain.alpha.sharding.timebertt.dev/"+controllerRingName, "true") objOld = obj.DeepCopy() Expect(p.Create(event.CreateEvent{Object: obj})).To(BeTrue()) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeTrue()) Expect(p.Generic(event.GenericEvent{Object: obj})).To(BeTrue()) }) It("should not handle assigned objects", func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "shard.alpha.sharding.timebertt.dev/"+controllerRingName, shardName) objOld = obj.DeepCopy() Expect(p.Create(event.CreateEvent{Object: obj})).To(BeFalse()) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeFalse()) Expect(p.Generic(event.GenericEvent{Object: obj})).To(BeFalse()) }) }) When("main predicate returns true", func() { BeforeEach(func() { mainPredicate = predicate.NewPredicateFuncs(func(client.Object) bool { return true }) }) It("should handle drained objects", func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "drain.alpha.sharding.timebertt.dev/"+controllerRingName, "true") objOld = obj.DeepCopy() Expect(p.Create(event.CreateEvent{Object: obj})).To(BeTrue()) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeTrue()) Expect(p.Generic(event.GenericEvent{Object: obj})).To(BeTrue()) }) It("should handle assigned objects", func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "shard.alpha.sharding.timebertt.dev/"+controllerRingName, shardName) objOld = obj.DeepCopy() Expect(p.Create(event.CreateEvent{Object: obj})).To(BeTrue()) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeTrue()) Expect(p.Generic(event.GenericEvent{Object: obj})).To(BeTrue()) }) It("should handle assigned and drained objects", func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "shard.alpha.sharding.timebertt.dev/"+controllerRingName, shardName) metav1.SetMetaDataLabel(&obj.ObjectMeta, "drain.alpha.sharding.timebertt.dev/"+controllerRingName, "true") objOld = obj.DeepCopy() Expect(p.Create(event.CreateEvent{Object: obj})).To(BeTrue()) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeTrue()) Expect(p.Generic(event.GenericEvent{Object: obj})).To(BeTrue()) }) }) }) ================================================ FILE: pkg/shard/controller/reconciler.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package controller import ( "context" "fmt" apierrors "k8s.io/apimachinery/pkg/api/errors" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" ) // Reconciler wraps another reconciler to ensure that the controller correctly handles the shard and drain labels. // It ignores any objects that are not assigned to the configured shard name and drains objects if instructed to by // the sharder. // You can use NewShardedReconciler to construct a sharded reconciler. type Reconciler struct { // Object is the object type of the controller. Object client.Object // Client is used to read and patch the controller's objects. Client client.Client // ControllerRingName is the name of the manager's ControllerRing. ControllerRingName string // ShardName is the shard ID of the manager. ShardName string // Do is the actual Reconciler. Do reconcile.Reconciler } // Reconcile implements reconcile.Reconciler. It performs the following steps: // 1) read the object using the client, forget the object if it is not found // 2) check whether the object is (still) assigned to this shard, forget the object otherwise // 3) acknowledge the drain operation if requested by removing the shard and drain label, skip reconciliation, and forget the object // 4) delegate reconciliation to the actual reconciler otherwise func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { log := logf.FromContext(ctx) obj := r.Object.DeepCopyObject().(client.Object) if err := r.Client.Get(ctx, request.NamespacedName, obj); err != nil { if apierrors.IsNotFound(err) { log.V(1).Info("Object is gone or not assigned to this shard anymore, stop reconciling") return reconcile.Result{}, nil } return reconcile.Result{}, fmt.Errorf("error retrieving object from store for determining responsibility: %w", err) } var ( labels = obj.GetLabels() labelShard = shardingv1alpha1.LabelShard(r.ControllerRingName) labelDrain = shardingv1alpha1.LabelDrain(r.ControllerRingName) ) // check if we are responsible for this object // Note that objects should already be filtered by the cache and the predicate for being assigned to this shard. // However, we still need to do a final check before reconciling here. The controller might requeue the object with // a delay or exponential. This might trigger another reconciliation even after observing a label change. if shard, ok := labels[labelShard]; !ok || shard != r.ShardName { log.V(1).Info("Ignoring object as it is not assigned to this shard", "shard", shard) return reconcile.Result{}, nil } if _, drain := labels[labelDrain]; drain { log.V(1).Info("Draining object") // acknowledge drain operation patch := client.MergeFromWithOptions(obj.DeepCopyObject().(client.Object), client.MergeFromWithOptimisticLock{}) delete(labels, labelShard) delete(labels, labelDrain) if err := r.Client.Patch(ctx, obj, patch); err != nil { return reconcile.Result{}, fmt.Errorf("error draining object: %w", err) } // forget object return reconcile.Result{}, nil } // we are responsible, reconcile object return r.Do.Reconcile(ctx, request) } ================================================ FILE: pkg/shard/controller/reconciler_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controller_test import ( "context" "fmt" "io" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gbytes" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/reconcile" . "github.com/timebertt/kubernetes-controller-sharding/pkg/shard/controller" ) var _ = Describe("#Reconciler", func() { var ( ctx context.Context logBuffer *Buffer controllerRingName string shardName string fakeClient client.Client r *Reconciler obj *corev1.Pod req reconcile.Request ) BeforeEach(func() { logBuffer = NewBuffer() ctx = logf.IntoContext(context.Background(), zap.New(zap.UseDevMode(true), zap.WriteTo(io.MultiWriter(logBuffer, GinkgoWriter)))) controllerRingName = "operator" shardName = "operator-0" fakeClient = fakeclient.NewFakeClient() r = &Reconciler{ Object: &corev1.Pod{}, Client: fakeClient, ControllerRingName: controllerRingName, ShardName: shardName, } obj = &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", Namespace: "bar", }, } req = reconcile.Request{NamespacedName: client.ObjectKeyFromObject(obj)} }) JustBeforeEach(func() { if obj != nil { Expect(fakeClient.Create(ctx, obj)).To(Succeed()) } }) When("the object does not exist", func() { BeforeEach(func() { obj = nil }) It("should ignore the request", func() { Expect(r.Reconcile(ctx, req)).To(BeZero()) Eventually(logBuffer).Should(Say("Object is gone")) }) }) When("the object is assigned to another shard", func() { BeforeEach(func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "shard.alpha.sharding.timebertt.dev/"+controllerRingName, "other") }) It("should ignore the request", func() { Expect(r.Reconcile(ctx, req)).To(BeZero()) Eventually(logBuffer).Should(Say("Ignoring object as it is not assigned to this shard")) }) }) When("the object is assigned to this shard", func() { BeforeEach(func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "shard.alpha.sharding.timebertt.dev/"+controllerRingName, shardName) }) When("the object is drained", func() { BeforeEach(func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "drain.alpha.sharding.timebertt.dev/"+controllerRingName, "true") }) It("should remove the shard and drain label", func() { Expect(r.Reconcile(ctx, req)).To(BeZero()) Eventually(logBuffer).Should(Say("Draining object")) Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(obj), obj)).To(Succeed()) Expect(obj.GetLabels()).Should(BeEmpty()) }) }) When("the object is not drained", func() { var ( result reconcile.Result err error called int ) BeforeEach(func() { result, err = reconcile.Result{}, nil called = 0 r.Do = reconcile.Func(func(context.Context, reconcile.Request) (reconcile.Result, error) { called++ return result, err }) }) It("should call the reconciler and return its result", func() { Expect(r.Reconcile(ctx, req)).To(BeZero()) Expect(called).To(Equal(1)) result = reconcile.Result{Requeue: true} Expect(r.Reconcile(ctx, req)).To(Equal(reconcile.Result{Requeue: true})) Expect(called).To(Equal(2)) result = reconcile.Result{} err = fmt.Errorf("foo") Expect(r.Reconcile(ctx, req)).Error().To(MatchError("foo")) Expect(called).To(Equal(3)) }) }) }) }) ================================================ FILE: pkg/shard/lease/lease.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package lease import ( "context" "encoding/json" "errors" "fmt" "io/fs" "os" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" coordinationv1client "k8s.io/client-go/kubernetes/typed/coordination/v1" "k8s.io/client-go/rest" "k8s.io/client-go/tools/leaderelection/resourcelock" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" ) // Options provides the required configuration to create a new shard lease. type Options struct { // ControllerRingName specifies the name of the ControllerRing that the shard belongs to. ControllerRingName string // LeaseNamespace determines the namespace in which the shard lease will be created. // Defaults to the pod's namespace if running in-cluster. LeaseNamespace string // ShardName determines the name of the shard. This will be used as the lease name as well as the lease's // holderIdentity. // Defaults to os.Hostname(). ShardName string } // NewResourceLock returns a new resource lock that implements the shard lease. // Pass this to the leader elector, e.g., leaderelection.LeaderElectionConfig.Lock (if using plain client-go) or // manager.Options.LeaderElectionResourceLockInterface (if using controller-runtime). func NewResourceLock(config *rest.Config, options Options) (resourcelock.Interface, error) { // Construct client for leader election rest.AddUserAgent(config, "shard-lease") // We use plain client-go here instead of controller-runtime to avoid pulling in the controller-runtime dependency // for projects that want to use this helper but don't use controller-runtime. coordinationClient, err := coordinationv1client.NewForConfig(config) if err != nil { return nil, err } if options.ControllerRingName == "" { return nil, errors.New("ControllerRingName is required") } // default shard name to hostname if not set if options.ShardName == "" { options.ShardName, err = os.Hostname() if err != nil { return nil, fmt.Errorf("error getting hostname: %w", err) } } // default namespace to pod's namespace if running in-cluster if options.LeaseNamespace == "" { options.LeaseNamespace, err = getInClusterNamespace() if err != nil { return nil, fmt.Errorf("unable to determine shard lease namespace: %w", err) } } return &LeaseLock{ LeaseMeta: metav1.ObjectMeta{ Namespace: options.LeaseNamespace, Name: options.ShardName, }, Client: coordinationClient, LockConfig: resourcelock.ResourceLockConfig{ Identity: options.ShardName, }, Labels: map[string]string{ shardingv1alpha1.LabelControllerRing: options.ControllerRingName, }, }, nil } // LeaseLock implements resourcelock.Interface but is able to add labels to the Lease. // The implementation is based resourclock.LeaseLock and shares some helper functions with it. // nolint:revive // don't rename LeaseLock to stay close to the original implementation in client-go. type LeaseLock struct { // LeaseMeta should contain a Name and a Namespace of a // LeaseMeta object that the LeaderElector will attempt to lead. LeaseMeta metav1.ObjectMeta Client coordinationv1client.LeasesGetter LockConfig resourcelock.ResourceLockConfig Labels map[string]string lease *coordinationv1.Lease } // Get returns the election record from a Lease spec func (ll *LeaseLock) Get(ctx context.Context) (*resourcelock.LeaderElectionRecord, []byte, error) { lease, err := ll.Client.Leases(ll.LeaseMeta.Namespace).Get(ctx, ll.LeaseMeta.Name, metav1.GetOptions{}) if err != nil { return nil, nil, err } ll.lease = lease record := resourcelock.LeaseSpecToLeaderElectionRecord(&ll.lease.Spec) recordByte, err := json.Marshal(*record) if err != nil { return nil, nil, err } return record, recordByte, nil } // Create attempts to create a Lease func (ll *LeaseLock) Create(ctx context.Context, ler resourcelock.LeaderElectionRecord) error { var err error ll.lease, err = ll.Client.Leases(ll.LeaseMeta.Namespace).Create(ctx, &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: ll.LeaseMeta.Name, Namespace: ll.LeaseMeta.Namespace, Labels: ll.Labels, }, Spec: resourcelock.LeaderElectionRecordToLeaseSpec(&ler), }, metav1.CreateOptions{}) return err } // Update will update an existing Lease spec. func (ll *LeaseLock) Update(ctx context.Context, ler resourcelock.LeaderElectionRecord) error { if ll.lease == nil { return errors.New("lease not initialized, call Get or Create first") } // don't set labels map on ll.lease directly, otherwise we might overwrite labels managed by the sharder mergeLabels(&ll.lease.ObjectMeta, ll.Labels) ll.lease.Spec = resourcelock.LeaderElectionRecordToLeaseSpec(&ler) lease, err := ll.Client.Leases(ll.LeaseMeta.Namespace).Update(ctx, ll.lease, metav1.UpdateOptions{}) if err != nil { return err } ll.lease = lease return nil } // RecordEvent does nothing, as recording events on shard leases is not meaningful. func (ll *LeaseLock) RecordEvent(string) {} // Describe is used to convert details on current resource lock // into a string func (ll *LeaseLock) Describe() string { return fmt.Sprintf("%v/%v", ll.LeaseMeta.Namespace, ll.LeaseMeta.Name) } // Identity returns the Identity of the lock func (ll *LeaseLock) Identity() string { return ll.LockConfig.Identity } func mergeLabels(obj *metav1.ObjectMeta, labels map[string]string) { for key, value := range labels { metav1.SetMetaDataLabel(obj, key, value) } } // allow overwriting file system for testing purposes var fsys = os.DirFS("/") const inClusterNamespacePath = "var/run/secrets/kubernetes.io/serviceaccount/namespace" // getInClusterNamespace determines the namespace that this binary is running in, if running in a cluster. // For this, it consults the ServiceAccount mount. If the binary is not running in a cluster or the pod doesn't mount a // ServiceAccount, it returns an error. func getInClusterNamespace() (string, error) { // Check whether the namespace file exists. // If not, we are not running in cluster so can't guess the namespace. if _, err := fs.Stat(fsys, inClusterNamespacePath); os.IsNotExist(err) { return "", fmt.Errorf("not running in cluster, please specify LeaseNamespace") } else if err != nil { return "", fmt.Errorf("error checking namespace file: %w", err) } // Load the namespace file and return its content namespace, err := fs.ReadFile(fsys, inClusterNamespacePath) if err != nil { return "", fmt.Errorf("error reading namespace file: %w", err) } return string(namespace), nil } ================================================ FILE: pkg/shard/lease/lease_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package lease_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestLease(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Shard Library Lease Suite") } ================================================ FILE: pkg/shard/lease/lease_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package lease import ( "context" "os" "testing/fstest" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/fake" coordinationv1client "k8s.io/client-go/kubernetes/typed/coordination/v1" "k8s.io/client-go/rest" "k8s.io/client-go/tools/leaderelection/resourcelock" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) var _ = Describe("LeaseLock", func() { const ( namespace = "default" controllerRingName = "operator" shardName = "operator-a" ) var ctx context.Context BeforeEach(func() { ctx = context.Background() fsys = fstest.MapFS{ "var/run/secrets/kubernetes.io/serviceaccount/namespace": &fstest.MapFile{ Data: []byte(namespace), }, } }) Describe("#NewResourceLock", func() { var ( restConfig *rest.Config options Options ) BeforeEach(func() { restConfig = &rest.Config{} options = Options{ ControllerRingName: controllerRingName, LeaseNamespace: "operator-system", ShardName: shardName, } }) It("should fail if ControllerRingName is empty", func() { options.ControllerRingName = "" Expect(NewResourceLock(restConfig, options)).Error().To(MatchError("ControllerRingName is required")) }) It("should use the configured namespace and name", func() { resourceLock, err := NewResourceLock(restConfig, options) Expect(err).NotTo(HaveOccurred()) leaseLock := resourceLock.(*LeaseLock) Expect(leaseLock.LeaseMeta.Namespace).To(Equal(options.LeaseNamespace)) Expect(leaseLock.LeaseMeta.Name).To(Equal(options.ShardName)) Expect(leaseLock.Identity()).To(Equal(leaseLock.LeaseMeta.Name), "identity should equal the shard name") }) It("should default the name to the hostname", func() { options.ShardName = "" hostname, err := os.Hostname() Expect(err).NotTo(HaveOccurred()) resourceLock, err := NewResourceLock(restConfig, options) Expect(err).NotTo(HaveOccurred()) leaseLock := resourceLock.(*LeaseLock) Expect(leaseLock.LeaseMeta.Name).To(Equal(hostname)) Expect(leaseLock.Identity()).To(Equal(leaseLock.LeaseMeta.Name), "identity should equal the shard name") }) It("should default the namespace to the in-cluster namespace", func() { options.LeaseNamespace = "" resourceLock, err := NewResourceLock(restConfig, options) Expect(err).NotTo(HaveOccurred()) leaseLock := resourceLock.(*LeaseLock) Expect(leaseLock.LeaseMeta.Namespace).To(Equal(namespace)) }) It("should fail if the in-cluster namespace cannot be determined", func() { options.LeaseNamespace = "" fsys = fstest.MapFS{} Expect(NewResourceLock(restConfig, options)).Error().To(MatchError(And( ContainSubstring("not running in cluster"), ContainSubstring("please specify LeaseNamespace"), ))) }) }) Describe("#LeaseLock", func() { var ( lock resourcelock.Interface fakeClient coordinationv1client.LeasesGetter lease *coordinationv1.Lease ) BeforeEach(func() { var err error lock, err = NewResourceLock(&rest.Config{}, Options{ ControllerRingName: controllerRingName, LeaseNamespace: namespace, ShardName: shardName, }) Expect(err).NotTo(HaveOccurred()) fakeClient = fake.NewClientset().CoordinationV1() lock.(*LeaseLock).Client = fakeClient lease = &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, Name: shardName, }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To(shardName), }, } Expect(fakeClient.Leases(lease.Namespace).Create(ctx, lease, metav1.CreateOptions{})).Error().To(Succeed()) }) Describe("#Get", func() { It("should return NotFound if the lease does not exist", func() { Expect(fakeClient.Leases(lease.Namespace).Delete(ctx, lease.Name, metav1.DeleteOptions{})).To(Succeed()) Expect(lock.Get(ctx)).Error().To(BeNotFoundError()) }) It("should return the existing lease", func() { record, _, err := lock.Get(ctx) Expect(err).NotTo(HaveOccurred()) Expect(record).NotTo(BeNil()) Expect(record.HolderIdentity).To(Equal(*lease.Spec.HolderIdentity)) }) }) Describe("#Create", func() { It("should create the lease if it does not exist", func() { Expect(fakeClient.Leases(lease.Namespace).Delete(ctx, lease.Name, metav1.DeleteOptions{})).To(Succeed()) Expect(lock.Create(ctx, resourcelock.LeaderElectionRecord{ HolderIdentity: "foo", })).To(Succeed()) Expect(fakeClient.Leases(lease.Namespace).Get(ctx, lease.Name, metav1.GetOptions{})).To(And( HaveField("ObjectMeta", And( HaveField("Namespace", Equal(namespace)), HaveField("Name", Equal(shardName)), HaveField("Labels", Equal(map[string]string{ "alpha.sharding.timebertt.dev/controllerring": controllerRingName, })), )), HaveField("Spec.HolderIdentity", Equal(ptr.To("foo"))), )) }) }) Describe("#Update", func() { It("should fail if lock is not initialized yet", func() { Expect(lock.Update(ctx, resourcelock.LeaderElectionRecord{ HolderIdentity: "foo", })).To(MatchError(ContainSubstring("not initialized"))) }) It("should update the lease", func() { Expect(lock.Get(ctx)).Error().To(Succeed()) Expect(lock.Update(ctx, resourcelock.LeaderElectionRecord{ HolderIdentity: "foo", })).To(Succeed()) Expect(fakeClient.Leases(lease.Namespace).Get(ctx, lease.Name, metav1.GetOptions{})).To(And( HaveField("ObjectMeta", And( HaveField("Namespace", Equal(namespace)), HaveField("Name", Equal(shardName)), HaveField("Labels", Equal(map[string]string{ "alpha.sharding.timebertt.dev/controllerring": controllerRingName, })), )), HaveField("Spec.HolderIdentity", Equal(ptr.To("foo"))), )) }) It("should keep externally managed labels", func() { metav1.SetMetaDataLabel(&lease.ObjectMeta, "foo", "bar") Expect(fakeClient.Leases(lease.Namespace).Update(ctx, lease, metav1.UpdateOptions{})).Error().To(Succeed()) Expect(lock.Get(ctx)).Error().To(Succeed()) Expect(lock.Update(ctx, resourcelock.LeaderElectionRecord{ HolderIdentity: "foo", })).To(Succeed()) Expect(fakeClient.Leases(lease.Namespace).Get(ctx, lease.Name, metav1.GetOptions{})).To( HaveField("ObjectMeta.Labels", Equal(map[string]string{ "foo": "bar", "alpha.sharding.timebertt.dev/controllerring": controllerRingName, })), ) }) }) Describe("#RecordEvent", func() { It("should do nothing", func() { lock.RecordEvent("foo") }) }) Describe("#Describe", func() { It("should return the lease key", func() { Expect(lock.Describe()).To(Equal(client.ObjectKeyFromObject(lease).String())) }) }) Describe("#Identity()", func() { It("should return the lease name", func() { Expect(lock.Identity()).To(Equal(lease.Name)) }) }) }) Describe("#getInClusterNamespace", func() { It("should fail because namespace file does not exist", func() { fsys = fstest.MapFS{} Expect(getInClusterNamespace()).Error().To(MatchError(ContainSubstring("not running in cluster"))) }) It("should return content of namespace file", func() { Expect(getInClusterNamespace()).To(Equal(namespace)) }) }) }) ================================================ FILE: pkg/sharding/consistenthash/benchmark_test.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package consistenthash import ( "fmt" "math" "testing" ) func TestDistribution(t *testing.T) { ring := New(DefaultHash, DefaultTokensPerNode) hosts := generateHostnames(10) dist := make(map[string]float64, len(hosts)) ring.AddNodes(hosts...) for _, host := range hosts { dist[host] = 0 } // fmt.Println("Virtual Nodes:") last := ring.tokens[len(ring.tokens)-1] for _, token := range ring.tokens { node := ring.tokenToNode[token] percentage := float64(token-last) / math.MaxUint64 dist[node] += percentage // fmt.Printf("\t%016x (%.5f): %.5f -> %s\n", token, float64(token)/math.MaxUint64, percentage, node) last = token } fmt.Println("Nodes distribution:") for _, host := range hosts { fmt.Printf("\t%s: %.5f\n", host, dist[host]) } } func generateHostnames(n int) []string { hosts := make([]string, n) for i := range hosts { host := fmt.Sprintf("10.42.0.%d", i) hosts[i] = host } return hosts } func benchmarkRing(nodes int, tokensPerNode int, b *testing.B) { hosts := generateHostnames(nodes) b.ResetTimer() for n := 0; n < b.N; n++ { ring := New(DefaultHash, tokensPerNode, hosts...) ring.Hash("Website.webhosting.timebertt.dev/project-foo/homepage") } } func BenchmarkRing3_100(b *testing.B) { benchmarkRing(3, 100, b) } func BenchmarkRing3_1000(b *testing.B) { benchmarkRing(3, 1000, b) } func BenchmarkRing5_100(b *testing.B) { benchmarkRing(5, 100, b) } func BenchmarkRing5_1000(b *testing.B) { benchmarkRing(5, 1000, b) } func BenchmarkRing10_100(b *testing.B) { benchmarkRing(10, 100, b) } func BenchmarkRing10_1000(b *testing.B) { benchmarkRing(10, 1000, b) } ================================================ FILE: pkg/sharding/consistenthash/consistenthash_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package consistenthash_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestConsistentHash(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Consistent Hash Suite") } ================================================ FILE: pkg/sharding/consistenthash/ring.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package consistenthash import ( "slices" "strconv" "github.com/cespare/xxhash/v2" ) // Hash is a function computing a 64-bit digest. type Hash func(data string) uint64 // DefaultHash is the default Hash used by Ring. var DefaultHash Hash = xxhash.Sum64String // DefaultTokensPerNode is the default number of virtual nodes per node. const DefaultTokensPerNode = 100 // New creates a new hash ring with the given configuration and adds the given nodes. // The given Hash (or DefaultHash if nil) is used to hash nodes and keys (strings). // Each node is assigned tokensPerNode tokens (or DefaultTokensPerNode if <= 0) – aka. virtual nodes – for a more // uniform key distribution. func New(hash Hash, tokensPerNode int, initialNodes ...string) *Ring { if hash == nil { hash = DefaultHash } if tokensPerNode <= 0 { tokensPerNode = DefaultTokensPerNode } numTokens := len(initialNodes) * tokensPerNode r := &Ring{ hash: hash, tokensPerNode: tokensPerNode, tokens: make([]uint64, 0, numTokens), tokenToNode: make(map[uint64]string, numTokens), } r.AddNodes(initialNodes...) return r } // Ring implements consistent hashing, aka. ring hash (not thread-safe). // It hashes nodes and keys (strings) onto a ring of tokens. Keys are mapped to the next token (node) on the ring. // Nodes cannot be removed. Instantiate a new Ring instead. type Ring struct { hash Hash tokensPerNode int tokens []uint64 tokenToNode map[uint64]string } // IsEmpty returns true if there are no nodes in this Ring. func (r *Ring) IsEmpty() bool { return len(r.tokens) == 0 } // AddNodes adds hash tokens for the given nodes to this Ring. func (r *Ring) AddNodes(nodes ...string) { for _, node := range nodes { for i := 0; i < r.tokensPerNode; i++ { t := r.hash(node + strconv.FormatInt(int64(i), 10)) r.tokens = append(r.tokens, t) r.tokenToNode[t] = node } } // sort all tokens on the ring for binary searches slices.Sort(r.tokens) } // Hash hashes the given key onto the ring of tokens and returns the node that belongs to the next token on the ring. func (r *Ring) Hash(key string) string { if r.IsEmpty() { return "" } // Hash key and find the next virtual node on the ring h := r.hash(key) i, _ := slices.BinarySearch(r.tokens, h) // walked the whole ring, next virtual node is the first one if i == len(r.tokens) { i = 0 } return r.tokenToNode[r.tokens[i]] } ================================================ FILE: pkg/sharding/consistenthash/ring_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package consistenthash_test import ( "strings" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/consistenthash" ) var _ = Describe("Ring", func() { Describe("#New", func() { It("should initialize a new Ring", func() { ring := New(nil, 0, "foo") Expect(ring).NotTo(BeNil()) Expect(ring.IsEmpty()).To(BeFalse()) }) }) Describe("#IsEmpty", func() { It("should true if there are no nodes", func() { ring := New(nil, 0) Expect(ring.IsEmpty()).To(BeTrue()) ring.AddNodes("foo") Expect(ring.IsEmpty()).To(BeFalse()) }) }) Describe("#Hash", func() { It("should use the configured hash function", func() { ring := New(func(data string) uint64 { if strings.HasPrefix(data, "foo") { // map all foo* nodes and keys to 1 return 1 } return 2 }, 1, "foo", "bar") Expect(ring.Hash("foo")).To(Equal("foo")) Expect(ring.Hash("bar")).To(Equal("bar")) Expect(ring.Hash("baz")).To(Equal("bar")) }) It("should use the default hash function", func() { ring := New(nil, 0, "foo", "bar") Expect(ring.Hash("1")).NotTo(Equal(ring.Hash("10"))) }) It("should return the empty string if there are no nodes", func() { ring := New(nil, 0) Expect(ring.Hash("foo")).To(BeEmpty()) }) It("should return the first node when walking the whole ring", func() { ring := New(func(data string) uint64 { if strings.HasPrefix(data, "foo") { // map all foo* nodes and keys to 1 return 1 } if strings.HasPrefix(data, "bar") { // map all bar* nodes and keys to 1 return 2 } return 3 }, 1, "foo", "bar") Expect(ring.Hash("foo")).To(Equal("foo")) Expect(ring.Hash("bar")).To(Equal("bar")) Expect(ring.Hash("baz")).To(Equal("foo")) }) }) }) ================================================ FILE: pkg/sharding/handler/controllerring.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package handler import ( "context" coordinationv1 "k8s.io/api/coordination/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/handler" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" ) var handlerLog = logf.Log.WithName("handler") // MapControllerRingToLeases maps a ControllerRing to all matching shard leases. func MapControllerRingToLeases(reader client.Reader) handler.MapFunc { return func(ctx context.Context, obj client.Object) []reconcile.Request { controllerRing, ok := obj.(*shardingv1alpha1.ControllerRing) if !ok { return nil } leaseList := &coordinationv1.LeaseList{} if err := reader.List(ctx, leaseList, client.MatchingLabelsSelector{Selector: controllerRing.LeaseSelector()}); err != nil { handlerLog.Error(err, "failed listing Leases for ControllerRing", "controllerRing", client.ObjectKeyFromObject(controllerRing)) return nil } requests := make([]reconcile.Request, 0, len(leaseList.Items)) for _, lease := range leaseList.Items { requests = append(requests, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(&lease)}) } return requests } } ================================================ FILE: pkg/sharding/handler/controllerring_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package handler_test import ( "context" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" coordinationv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" . "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/handler" ) var _ = Describe("ControllerRing", func() { var ( ctx context.Context fakeClient client.Client ) BeforeEach(func() { ctx = context.Background() fakeClient = fakeclient.NewFakeClient() }) Describe("#MapControllerRingToLeases", func() { var ( mapFunc handler.MapFunc obj *shardingv1alpha1.ControllerRing ) BeforeEach(func() { mapFunc = MapControllerRingToLeases(fakeClient) obj = &shardingv1alpha1.ControllerRing{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", }, } lease := &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: "foo-1", Namespace: "foo-system", Labels: map[string]string{ "alpha.sharding.timebertt.dev/controllerring": "foo", }, }, } Expect(fakeClient.Create(ctx, lease.DeepCopy())).To(Succeed()) lease.Name = "foo-2" Expect(fakeClient.Create(ctx, lease.DeepCopy())).To(Succeed()) lease.Name = "foo-3" lease.Labels["alpha.sharding.timebertt.dev/controllerring"] = "bar" Expect(fakeClient.Create(ctx, lease.DeepCopy())).To(Succeed()) lease.Name = "foo-4" lease.Labels = nil Expect(fakeClient.Create(ctx, lease.DeepCopy())).To(Succeed()) }) It("should ignore other object kinds", func() { Expect(mapFunc(ctx, &corev1.Pod{})).To(BeEmpty()) }) It("should return requests for all matching leases", func() { Expect(mapFunc(ctx, obj)).To(ConsistOf( reconcile.Request{NamespacedName: types.NamespacedName{Namespace: "foo-system", Name: "foo-1"}}, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: "foo-system", Name: "foo-2"}}, )) }) }) }) ================================================ FILE: pkg/sharding/handler/handler_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package handler_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestHandler(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Sharding Handlers Suite") } ================================================ FILE: pkg/sharding/handler/lease.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package handler import ( "context" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" ) // MapLeaseToControllerRing maps a shard lease to its ControllerRing. func MapLeaseToControllerRing(_ context.Context, obj client.Object) []reconcile.Request { ring := obj.GetLabels()[shardingv1alpha1.LabelControllerRing] if ring == "" { return nil } return []reconcile.Request{{NamespacedName: client.ObjectKey{Name: ring}}} } ================================================ FILE: pkg/sharding/handler/lease_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package handler_test import ( "context" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" . "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/handler" ) var _ = Describe("Lease", func() { var ctx context.Context BeforeEach(func() { ctx = context.Background() }) Describe("#MapLeaseToControllerRing", func() { var ( mapFunc handler.MapFunc obj *coordinationv1.Lease ) BeforeEach(func() { mapFunc = MapLeaseToControllerRing obj = &coordinationv1.Lease{} }) It("should ignore unlabelled leases", func() { Expect(mapFunc(ctx, obj)).To(BeEmpty()) }) It("should ignore leases with empty label", func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "alpha.sharding.timebertt.dev/controllerring", "") Expect(mapFunc(ctx, obj)).To(BeEmpty()) }) It("should correctly map leases with present label", func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "alpha.sharding.timebertt.dev/controllerring", "foo") Expect(mapFunc(ctx, obj)).To(ConsistOf(reconcile.Request{NamespacedName: client.ObjectKey{Name: "foo"}})) }) }) }) ================================================ FILE: pkg/sharding/key/key.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package key import ( "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" "sigs.k8s.io/controller-runtime/pkg/client" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" ) // FuncForResource returns the key function that maps the given resource or its controller depending on whether // the resource is listed as a resource or controlled resource in the given ring. func FuncForResource(gr metav1.GroupResource, ring *shardingv1alpha1.ControllerRing) (Func, error) { ringResources := sets.New[metav1.GroupResource]() controlledResources := sets.New[metav1.GroupResource]() for _, ringResource := range ring.Spec.Resources { ringResources.Insert(ringResource.GroupResource) for _, controlledResource := range ringResource.ControlledResources { controlledResources.Insert(controlledResource) } } switch { case ringResources.Has(gr): return ForObject, nil case controlledResources.Has(gr): return ForController, nil } return nil, fmt.Errorf("object's resource %q was not found in ControllerRing", gr.String()) } // Func maps objects to hash keys. // It returns an error if the prerequisites for sharding the given object are not fulfilled. // If the returned key is empty, the object should not be assigned. type Func func(client.Object) (string, error) // ForObject returns a ring key for the given object itself. // It needs the TypeMeta (GVK) to be set, which is not set on objects after decoding by default. func ForObject(obj client.Object) (string, error) { // We can't use the object's UID, as it is unset during admission for CREATE requests. // Instead, we need to calculate a unique ID ourselves. The ID has this pattern (see forMetadata): // group/version/kind/namespace/name // With this, different object instances with the same name will use the same hash key, which sounds acceptable. // We can only use fields that are also present in owner references as we need to assign owners and ownees to the same // shard. E.g., we can't use generateName. gvk := obj.GetObjectKind().GroupVersionKind() if gvk.Empty() { return "", fmt.Errorf("apiVersion and kind must not be empty") } if obj.GetName() == "" { if obj.GetGenerateName() != "" { // If generateName is used, name is unset during admission for CREATE requests. // We can't support assigning such objects during admission because we will not be able to calculate a unique // object ID that we can also reconstruct later on for owned objects just by looking at the object itself. // We could use a cache lookup though, but this would restrict scalability of the sharding solution again. // Generally, this tradeoff seems acceptable, as generateName is mostly used on owned objects, but rarely the // owner itself. In such case, ForController will be used instead, which doesn't care about the object's own // name but only that of the owner. // If generateName is used nevertheless, respond with a proper error. // We could assign the object after creation, however we can't use a watch cache because of the mentioned // scalability limitations. A possible solution could only do some optimistic delayed enqueuing. return "", fmt.Errorf("generateName is not supported on ring resources that are not controlled by another resource") } return "", fmt.Errorf("name must not be empty") } // Namespace can be empty for cluster-scoped resources. Only check the name field as an optimistic check for // preventing wrong usage of the function. return forMetadata(gvk.Group, gvk.Kind, obj.GetNamespace(), obj.GetName()), nil } // ForController returns a ring key for the controller of the given object. // It returns an empty key if the object doesn't have an ownerReference with controller=true". func ForController(obj client.Object) (string, error) { ref := metav1.GetControllerOf(obj) if ref == nil { return "", nil } if ref.APIVersion == "" { return "", fmt.Errorf("apiVersion of controller reference must not be empty") } if ref.Kind == "" { return "", fmt.Errorf("kind of controller reference must not be empty") } if ref.Name == "" { return "", fmt.Errorf("name of controller reference must not be empty") } gv, err := schema.ParseGroupVersion(ref.APIVersion) if err != nil { return "", fmt.Errorf("invalid apiVersion of controller reference: %w", err) } return forMetadata(gv.Group, ref.Kind, obj.GetNamespace(), ref.Name), nil } func forMetadata(group, kind, namespace, name string) string { return group + "/" + kind + "/" + namespace + "/" + name } ================================================ FILE: pkg/sharding/key/key_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package key_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestKey(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Sharding Key Suite") } ================================================ FILE: pkg/sharding/key/key_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package key_test import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" . "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/key" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) var _ = Describe("#FuncForResource", func() { var controllerRing *shardingv1alpha1.ControllerRing BeforeEach(func() { controllerRing = &shardingv1alpha1.ControllerRing{ Spec: shardingv1alpha1.ControllerRingSpec{ Resources: []shardingv1alpha1.RingResource{ { GroupResource: metav1.GroupResource{ Group: "operator", Resource: "foo", }, ControlledResources: []metav1.GroupResource{ { Group: "operator", Resource: "controlled", }, { Resource: "foo", }, }, }, { GroupResource: metav1.GroupResource{ Resource: "foo", }, }, }, }, } }) It("should return an error if the resource is not part of the ring", func() { Expect(FuncForResource(metav1.GroupResource{ Resource: "bar", }, controllerRing)).Error().To( MatchError(ContainSubstring("not found")), ) }) It("should return ForObject if the resource is a main resource of the ring", func() { Expect(FuncForResource(metav1.GroupResource{ Group: "operator", Resource: "foo", }, controllerRing)).To( BeFunc(ForObject), ) }) It("should return ForController if the resource is a controlled resource of the ring", func() { Expect(FuncForResource(metav1.GroupResource{ Group: "operator", Resource: "controlled", }, controllerRing)).To( BeFunc(ForController), ) }) It("should return ForObject if the resource is a main and controlled resource of the ring", func() { Expect(FuncForResource(metav1.GroupResource{ Resource: "foo", }, controllerRing)).To( BeFunc(ForObject), ) }) }) var _ = Describe("#ForObject", func() { var obj *appsv1.Deployment BeforeEach(func() { obj = &appsv1.Deployment{} obj.GetObjectKind().SetGroupVersionKind(appsv1.SchemeGroupVersion.WithKind("Deployment")) obj.Name = "foo" obj.Namespace = "bar" }) It("should return an error if the object has no TypeMeta", func() { Expect(ForObject(&appsv1.Deployment{})).Error().To(MatchError("apiVersion and kind must not be empty")) }) It("should return an error if the object has no name", func() { obj.Name = "" Expect(ForObject(obj)).Error().To(MatchError("name must not be empty")) obj.GenerateName = "foo-" Expect(ForObject(obj)).Error().To(MatchError(ContainSubstring("generateName is not supported"))) }) It("should return the object's hash key", func() { Expect(ForObject(obj)).To(Equal("apps/Deployment/bar/foo")) }) }) var _ = Describe("#ForController", func() { var obj *appsv1.Deployment BeforeEach(func() { obj = &appsv1.Deployment{} obj.SetOwnerReferences([]metav1.OwnerReference{ { APIVersion: "other/v1", Kind: "Bar", Name: "owner-but-not-controller", }, { APIVersion: "operator/v1", Kind: "Foo", Name: "foo", Controller: ptr.To(true), }, }) obj.Namespace = "bar" }) It("should return an empty key if the object has no controller ref", func() { Expect(ForController(&appsv1.Deployment{})).To(BeEmpty()) obj.OwnerReferences[1].Controller = nil Expect(ForController(obj)).To(BeEmpty()) }) It("should return an error if the controller ref has no apiVersion", func() { obj.OwnerReferences[1].APIVersion = "" Expect(ForController(obj)).Error().To(MatchError("apiVersion of controller reference must not be empty")) }) It("should return an error if the controller ref has no kind", func() { obj.OwnerReferences[1].Kind = "" Expect(ForController(obj)).Error().To(MatchError("kind of controller reference must not be empty")) }) It("should return an error if the controller ref has no name", func() { obj.OwnerReferences[1].Name = "" Expect(ForController(obj)).Error().To(MatchError("name of controller reference must not be empty")) }) It("should return an error if the controller ref has an invalid apiVersion", func() { obj.OwnerReferences[1].APIVersion = "foo/bar/v1" Expect(ForController(obj)).Error().To(MatchError(ContainSubstring("invalid apiVersion of controller reference"))) }) It("should return the controller's hash key", func() { Expect(ForController(obj)).To(Equal("operator/Foo/bar/foo")) }) }) ================================================ FILE: pkg/sharding/leases/leases_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package leases_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestLeases(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Leases Suite") } ================================================ FILE: pkg/sharding/leases/shards.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package leases import ( "time" coordinationv1 "k8s.io/api/coordination/v1" ) // Shard represents a single shard in a ring of controller instances. type Shard struct { // ID is the ID of this Shard, i.e., the name of the Lease object. ID string // State is the current state of this shard based on the times and durations of the Lease object. State ShardState // Times holds the parsed times and durations of the Lease object. Times Times } // Shards is a list of Shards. // This could also be a map, but a slice is deterministic in order. The methods returning a list are called way more // frequently than a lookup using ByID. type Shards []Shard // ByID returns the Shard with the given ID from the list of Shards. func (s Shards) ByID(id string) Shard { for _, shard := range s { if shard.ID == id { return shard } } return Shard{} } // AvailableShards returns the subset of available Shards as determined by IsAvailable. func (s Shards) AvailableShards() Shards { shards := make(Shards, 0, len(s)) for _, shard := range s { if shard.State.IsAvailable() { shards = append(shards, shard) } } return shards } // IDs returns the list of Shard IDs. func (s Shards) IDs() []string { ids := make([]string, len(s)) for i, shard := range s { ids[i] = shard.ID } return ids } // ToShards takes a list of Lease objects and transforms them to a list of Shards. func ToShards(leases []coordinationv1.Lease, now time.Time) Shards { shards := make(Shards, 0, len(leases)) for _, lease := range leases { shards = append(shards, ToShard(&lease, now)) } return shards } // ToShard takes a Lease object and transforms it to a Shard. func ToShard(lease *coordinationv1.Lease, now time.Time) Shard { times := ToTimes(lease, now) return Shard{ ID: lease.GetName(), Times: times, State: toState(lease, times), } } ================================================ FILE: pkg/sharding/leases/shards_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package leases_test import ( "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/gstruct" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" . "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/leases" ) var _ = Describe("Shards", func() { Describe("#ByID", func() { It("should return the matching shard", func() { shards := Shards{ {ID: "shard-1"}, {ID: "shard-2"}, {ID: "shard-3"}, } Expect(shards.ByID("shard-2").ID).To(Equal("shard-2")) }) It("should return a zero shard if the ID has not been found", func() { Expect(Shards{{ID: "shard-1"}}.ByID("shard-2").ID).To(BeZero()) Expect(Shards{}.ByID("shard-2").ID).To(BeZero()) Expect(Shards(nil).ByID("shard-2").ID).To(BeZero()) }) }) Describe("#AvailableShards", func() { It("should return the available shards", func() { shards := Shards{ {ID: "shard-1", State: Ready}, {ID: "shard-2", State: Expired}, {ID: "shard-3", State: Uncertain}, {ID: "shard-4", State: Dead}, {ID: "shard-5", State: Orphaned}, } Expect(shards.AvailableShards().IDs()).To(ConsistOf("shard-1", "shard-2", "shard-3")) }) }) Describe("#IDs", func() { It("should return the shard IDs", func() { shards := Shards{ {ID: "shard-1"}, {ID: "shard-2"}, } Expect(shards.IDs()).To(ConsistOf("shard-1", "shard-2")) }) }) Describe("#ToShards", func() { var ( now time.Time lease *coordinationv1.Lease ) BeforeEach(func() { now = time.Now() lease = &coordinationv1.Lease{ Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To("shard"), LeaseDurationSeconds: ptr.To[int32](10), AcquireTime: ptr.To(metav1.NewMicroTime(now.Add(-2 * time.Minute))), RenewTime: ptr.To(metav1.NewMicroTime(now.Add(-2 * time.Second))), }, } }) It("should correctly transform the lease objects", func() { leases := make([]coordinationv1.Lease, 2) leases[0] = *lease.DeepCopy() leases[0].Name = "shard-1" leases[0].Spec.HolderIdentity = ptr.To("shard-1") leases[1] = *lease.DeepCopy() leases[1].Name = "shard-2" leases[1].Spec.HolderIdentity = nil leases[1].Spec.LeaseDurationSeconds = ptr.To[int32](1) leases[1].Spec.AcquireTime = ptr.To(metav1.NewMicroTime(now)) leases[1].Spec.RenewTime = ptr.To(metav1.NewMicroTime(now)) Expect(ToShards(leases, now)).To(ConsistOf( gstruct.MatchAllFields(gstruct.Fields{ "ID": Equal("shard-1"), "State": Equal(Ready), "Times": gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{ "Expiration": Equal(now.Add(8 * time.Second)), }), }), gstruct.MatchAllFields(gstruct.Fields{ "ID": Equal("shard-2"), "State": Equal(Dead), "Times": gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{ "ToOrphaned": Equal(time.Second + time.Minute), }), }), )) }) }) }) ================================================ FILE: pkg/sharding/leases/state.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package leases import ( "time" coordinationv1 "k8s.io/api/coordination/v1" ) // ShardState represents a state of a single shard which determines whether it is available for assigning objects to it // or whether it is unhealthy. type ShardState int const ( // Unknown is the ShardState if the Lease is not present or misses required fields. Unknown ShardState = iota // Orphaned is the ShardState if the Lease has been in state Dead for at least 1 minute. Orphaned // Dead is the ShardState if the Lease is Uncertain and was successfully acquired by the sharder or if it was actively // released by the shard. Dead // Uncertain is the ShardState if the Lease has expired at least leaseDuration ago. Uncertain // Expired is the ShardState if the Lease has expired less than leaseDuration ago. Expired // Ready is the ShardState if the Lease is held by the shard and has not expired. Ready ) // KnownShardStates is a list of all known shard states. var KnownShardStates = []ShardState{Orphaned, Dead, Uncertain, Expired, Ready} // String returns a string representation of this ShardState. func (s ShardState) String() string { switch s { case Orphaned: return "orphaned" case Dead: return "dead" case Uncertain: return "uncertain" case Expired: return "expired" case Ready: return "ready" default: return "unknown" } } // StateFromString returns the ShardState matching the given string representation. func StateFromString(state string) ShardState { switch state { case "orphaned": return Orphaned case "dead": return Dead case "uncertain": return Uncertain case "expired": return Expired case "ready": return Ready default: return Unknown } } // IsAvailable returns true for shard states that should be considered for object assignment. func (s ShardState) IsAvailable() bool { return s >= Uncertain } // ToState returns the ShardState of the given Lease. func ToState(lease *coordinationv1.Lease, now time.Time) ShardState { return toState(lease, ToTimes(lease, now)) } func toState(lease *coordinationv1.Lease, t Times) ShardState { // check if lease was released or acquired by sharder if holder := lease.Spec.HolderIdentity; holder == nil || *holder == "" || *holder != lease.Name { if t.ToOrphaned <= 0 { return Orphaned } return Dead } switch { case t.ToUncertain <= 0: return Uncertain case t.ToExpired <= 0: return Expired } return Ready } ================================================ FILE: pkg/sharding/leases/state_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package leases_test import ( "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" . "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/leases" ) var _ = Describe("ShardState", func() { Describe("#String", func() { It("should return the state as a string", func() { Expect(Unknown.String()).To(Equal("unknown")) Expect(Orphaned.String()).To(Equal("orphaned")) Expect(Dead.String()).To(Equal("dead")) Expect(Uncertain.String()).To(Equal("uncertain")) Expect(Expired.String()).To(Equal("expired")) Expect(Ready.String()).To(Equal("ready")) Expect(ShardState(-1).String()).To(Equal("unknown")) }) }) Describe("#StateFromString", func() { It("should return the correct state matching the string", func() { Expect(StateFromString("unknown")).To(Equal(Unknown)) Expect(StateFromString("orphaned")).To(Equal(Orphaned)) Expect(StateFromString("dead")).To(Equal(Dead)) Expect(StateFromString("uncertain")).To(Equal(Uncertain)) Expect(StateFromString("expired")).To(Equal(Expired)) Expect(StateFromString("ready")).To(Equal(Ready)) Expect(StateFromString("foo")).To(Equal(Unknown)) }) }) Describe("#IsAvailable", func() { It("should return false for unavailable states", func() { Expect(Unknown.IsAvailable()).To(BeFalse()) Expect(Orphaned.IsAvailable()).To(BeFalse()) Expect(Dead.IsAvailable()).To(BeFalse()) }) It("should return true for available states", func() { Expect(Uncertain.IsAvailable()).To(BeTrue()) Expect(Expired.IsAvailable()).To(BeTrue()) Expect(Ready.IsAvailable()).To(BeTrue()) }) }) Describe("#ToState", func() { var ( now time.Time lease *coordinationv1.Lease ) BeforeEach(func() { now = time.Now() lease = &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: "shard", }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To("shard"), LeaseDurationSeconds: ptr.To[int32](10), AcquireTime: ptr.To(metav1.NewMicroTime(now.Add(-2 * time.Minute))), RenewTime: ptr.To(metav1.NewMicroTime(now.Add(-2 * time.Second))), }, } }) It("should return ready if lease has not expired", func() { Expect(ToState(lease, now)).To(Equal(Ready)) }) It("should return expired if lease has expired", func() { lease.Spec.RenewTime = ptr.To(metav1.NewMicroTime(now.Add(-15 * time.Second))) Expect(ToState(lease, now)).To(Equal(Expired)) }) It("should return expired if acquireTime is missing", func() { lease.Spec.AcquireTime = nil Expect(ToState(lease, now)).To(Equal(Expired)) }) It("should return expired if renewTime is missing", func() { lease.Spec.RenewTime = nil Expect(ToState(lease, now)).To(Equal(Expired)) }) It("should return expired if leaseDuration is missing", func() { lease.Spec.LeaseDurationSeconds = nil Expect(ToState(lease, now)).To(Equal(Expired)) }) It("should return uncertain if lease has expired more than leaseDuration ago", func() { lease.Spec.RenewTime = ptr.To(metav1.NewMicroTime(now.Add(-25 * time.Second))) Expect(ToState(lease, now)).To(Equal(Uncertain)) }) It("should return dead if lease has been released", func() { lease.Spec.HolderIdentity = nil Expect(ToState(lease, now)).To(Equal(Dead)) lease.Spec.HolderIdentity = ptr.To("") Expect(ToState(lease, now)).To(Equal(Dead)) }) It("should return dead if lease has been acquired by sharder", func() { lease.Spec.HolderIdentity = ptr.To("shardlease-controller") lease.Spec.LeaseDurationSeconds = ptr.To[int32](20) lease.Spec.AcquireTime = ptr.To(metav1.NewMicroTime(now)) lease.Spec.RenewTime = ptr.To(metav1.NewMicroTime(now)) Expect(ToState(lease, now)).To(Equal(Dead)) }) It("should return orphaned if lease has been released 1 minute and leaseDuration ago", func() { lease.Spec.HolderIdentity = nil lease.Spec.LeaseDurationSeconds = ptr.To[int32](1) lease.Spec.AcquireTime = ptr.To(metav1.NewMicroTime(now.Add(-time.Minute - time.Second))) lease.Spec.RenewTime = ptr.To(metav1.NewMicroTime(now.Add(-time.Minute - time.Second))) Expect(ToState(lease, now)).To(Equal(Orphaned)) }) It("should return orphaned if lease has been acquired by sharder 1 minute and ago", func() { lease.Spec.HolderIdentity = ptr.To("shardlease-controller") lease.Spec.LeaseDurationSeconds = ptr.To[int32](20) lease.Spec.AcquireTime = ptr.To(metav1.NewMicroTime(now.Add(-time.Minute - 20*time.Second))) lease.Spec.RenewTime = ptr.To(metav1.NewMicroTime(now.Add(-time.Minute - 20*time.Second))) Expect(ToState(lease, now)).To(Equal(Orphaned)) }) }) }) ================================================ FILE: pkg/sharding/leases/times.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package leases import ( "time" coordinationv1 "k8s.io/api/coordination/v1" ) const ( defaultLeaseDuration = 15 * time.Second leaseTTL = time.Minute ) // Times holds the parsed times and durations of the Lease object. type Times struct { // Expiration is the time when the Lease expires (RenewTime + LeaseDurationSeconds) Expiration time.Time // LeaseDuration is LeaseDurationSeconds represented as a Duration. LeaseDuration time.Duration // ToExpired is the duration until the Lease expires (Expiration - now). ToExpired time.Duration // ToUncertain is the duration until the Shard Lease becomes uncertain and should get acquired by the sharder // (ToExpired + LeaseDuration). ToUncertain time.Duration // ToOrphaned is the duration until the Lease becomes orphaned and should get cleaned up (ToExpired + leaseTTL). ToOrphaned time.Duration } // ToTimes parses the times and durations in the given Lease object and returns them in the Times representation. func ToTimes(lease *coordinationv1.Lease, now time.Time) Times { var ( t = Times{} acquireTime = lease.Spec.AcquireTime renewTime = lease.Spec.RenewTime durationSeconds = lease.Spec.LeaseDurationSeconds ) if acquireTime == nil || renewTime == nil || durationSeconds == nil { t.Expiration = now t.LeaseDuration = defaultLeaseDuration } else { t.LeaseDuration = time.Duration(*durationSeconds) * time.Second t.Expiration = renewTime.Add(t.LeaseDuration) } t.ToExpired = t.Expiration.Sub(now) t.ToUncertain = t.ToExpired + t.LeaseDuration // ToOrphaned only applies, if lease is released or acquired by sharder t.ToOrphaned = t.ToExpired + leaseTTL return t } ================================================ FILE: pkg/sharding/leases/times_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package leases_test import ( "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" . "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/leases" ) var _ = Describe("Times", func() { Describe("#ToTimes", func() { var ( now time.Time lease *coordinationv1.Lease ) BeforeEach(func() { now = time.Now() lease = &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: "shard", }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To("shard"), LeaseDurationSeconds: ptr.To[int32](10), AcquireTime: ptr.To(metav1.NewMicroTime(now.Add(-2 * time.Minute))), RenewTime: ptr.To(metav1.NewMicroTime(now.Add(-2 * time.Second))), }, } }) It("should return the correct times for a ready shard", func() { matchTimes(ToTimes(lease, now), Times{ Expiration: now.Add(8 * time.Second), LeaseDuration: 10 * time.Second, ToExpired: 8 * time.Second, ToUncertain: 18 * time.Second, ToOrphaned: 8*time.Second + time.Minute, }) }) It("should return the correct times for a lease acquired by the sharder", func() { lease.Spec.HolderIdentity = ptr.To("shardlease-controller") lease.Spec.LeaseDurationSeconds = ptr.To[int32](20) lease.Spec.AcquireTime = ptr.To(metav1.NewMicroTime(now.Add(-2 * time.Second))) lease.Spec.RenewTime = ptr.To(metav1.NewMicroTime(now.Add(-2 * time.Second))) matchTimes(ToTimes(lease, now), Times{ Expiration: now.Add(18 * time.Second), LeaseDuration: 20 * time.Second, ToExpired: 18 * time.Second, ToUncertain: 38 * time.Second, ToOrphaned: 18*time.Second + time.Minute, }) }) It("should return the correct times for a released lease", func() { lease.Spec.HolderIdentity = nil lease.Spec.LeaseDurationSeconds = ptr.To[int32](1) lease.Spec.AcquireTime = ptr.To(metav1.NewMicroTime(now)) lease.Spec.RenewTime = ptr.To(metav1.NewMicroTime(now)) matchTimes(ToTimes(lease, now), Times{ Expiration: now.Add(time.Second), LeaseDuration: time.Second, ToExpired: time.Second, ToUncertain: 2 * time.Second, ToOrphaned: time.Second + time.Minute, }) }) It("should set expiration to now if some field is missing", func() { expectedTimes := Times{ Expiration: now, LeaseDuration: 15 * time.Second, ToExpired: 0, ToUncertain: 15 * time.Second, ToOrphaned: time.Minute, } brokenLease := lease.DeepCopy() brokenLease.Spec.AcquireTime = nil matchTimes(ToTimes(brokenLease, now), expectedTimes) brokenLease = lease.DeepCopy() brokenLease.Spec.RenewTime = nil matchTimes(ToTimes(brokenLease, now), expectedTimes) brokenLease = lease.DeepCopy() brokenLease.Spec.LeaseDurationSeconds = nil matchTimes(ToTimes(brokenLease, now), expectedTimes) }) }) }) func matchTimes(actual, expected Times) { GinkgoHelper() Expect(actual.Expiration.String()).To(Equal(expected.Expiration.String()), "should match expected Expiration time") Expect(actual.LeaseDuration.String()).To(Equal(expected.LeaseDuration.String()), "should match expected LeaseDuration duration") Expect(actual.ToExpired.String()).To(Equal(expected.ToExpired.String()), "should match expected ToExpired duration") Expect(actual.ToUncertain.String()).To(Equal(expected.ToUncertain.String()), "should match expected ToUncertain duration") Expect(actual.ToOrphaned.String()).To(Equal(expected.ToOrphaned.String()), "should match expected ToOrphaned duration") } ================================================ FILE: pkg/sharding/predicate/controllerring.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package predicate import ( "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" ) // ControllerRingCreatedOrUpdated reacts on create and update events with generation changes but ignores delete // events. On deletion, there is nothing to do for the sharding controllers. func ControllerRingCreatedOrUpdated() predicate.Predicate { return predicate.And( predicate.GenerationChangedPredicate{}, // ignore deletion of ControllerRings predicate.Funcs{ CreateFunc: func(_ event.CreateEvent) bool { return true }, UpdateFunc: func(_ event.UpdateEvent) bool { return true }, DeleteFunc: func(_ event.DeleteEvent) bool { return false }, }, ) } ================================================ FILE: pkg/sharding/predicate/controllerring_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package predicate_test import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" . "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/predicate" ) var _ = Describe("ControllerRing", func() { var ( p predicate.Predicate obj, objOld *shardingv1alpha1.ControllerRing ) BeforeEach(func() { obj = &shardingv1alpha1.ControllerRing{ ObjectMeta: metav1.ObjectMeta{ Generation: 1, }, } objOld = obj.DeepCopy() }) Describe("#ControllerRingCreatedOrUpdated", func() { BeforeEach(func() { p = ControllerRingCreatedOrUpdated() }) It("should react on create events", func() { Expect(p.Create(event.CreateEvent{Object: obj})).To(BeTrue()) }) It("should react on spec updates", func() { obj.Generation++ obj.Spec.Resources = append(obj.Spec.Resources, shardingv1alpha1.RingResource{ GroupResource: metav1.GroupResource{Resource: "pods"}, }) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) }) It("should ignore status updates", func() { obj.Status.AvailableShards++ Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) }) It("should ignore delete events", func() { Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeFalse()) }) }) }) ================================================ FILE: pkg/sharding/predicate/lease.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package predicate import ( coordinationv1 "k8s.io/api/coordination/v1" "k8s.io/utils/clock" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/leases" ) // IsShardLease filters for events on Lease objects that have a non-empty label specifying the ControllerRing. func IsShardLease() predicate.Predicate { return predicate.NewPredicateFuncs(func(obj client.Object) bool { lease, ok := obj.(*coordinationv1.Lease) if !ok { return false } return lease.Labels[shardingv1alpha1.LabelControllerRing] != "" }) } // ShardLeaseStateChanged reacts on lease events where the shard's state changes. func ShardLeaseStateChanged(clock clock.PassiveClock) predicate.Predicate { return predicate.Funcs{ UpdateFunc: func(e event.UpdateEvent) bool { oldLease, ok := e.ObjectOld.(*coordinationv1.Lease) if !ok { return false } newLease, ok := e.ObjectNew.(*coordinationv1.Lease) if !ok { return false } // only react if the shard's state changed now := clock.Now() return leases.ToState(oldLease, now) != leases.ToState(newLease, now) }, } } // ShardLeaseAvailabilityChanged reacts on lease events where the shard's availability changes. func ShardLeaseAvailabilityChanged(clock clock.PassiveClock) predicate.Predicate { return predicate.Funcs{ CreateFunc: func(e event.CreateEvent) bool { lease, ok := e.Object.(*coordinationv1.Lease) if !ok { return false } // only react if the new shard is available right away return leases.ToState(lease, clock.Now()).IsAvailable() }, UpdateFunc: func(e event.UpdateEvent) bool { oldLease, ok := e.ObjectOld.(*coordinationv1.Lease) if !ok { return false } newLease, ok := e.ObjectNew.(*coordinationv1.Lease) if !ok { return false } // only react if the shard's availability changed now := clock.Now() return leases.ToState(oldLease, now).IsAvailable() != leases.ToState(newLease, now).IsAvailable() }, DeleteFunc: func(e event.DeleteEvent) bool { lease, ok := e.Object.(*coordinationv1.Lease) if !ok { return false } if e.DeleteStateUnknown { // If we missed the delete event, we cannot know the final state of the shard (available or not) for sure. // The included object might be stale, as we might have missed a relevant update before as well. // In this case, react for safety. return true } // only react if the removed shard was still available return leases.ToState(lease, clock.Now()).IsAvailable() }, } } ================================================ FILE: pkg/sharding/predicate/lease_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package predicate_test import ( "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" coordinationv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/clock/testing" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/leases" . "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/predicate" ) var _ = Describe("Lease", func() { var ( p predicate.Predicate fakeClock *testing.FakePassiveClock obj, objOld *coordinationv1.Lease ) BeforeEach(func() { fakeClock = testing.NewFakePassiveClock(time.Now()) obj = &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: "foo-0", }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To("foo-0"), LeaseDurationSeconds: ptr.To[int32](10), AcquireTime: ptr.To(metav1.NewMicroTime(fakeClock.Now().Add(-5 * time.Minute))), RenewTime: ptr.To(metav1.NewMicroTime(fakeClock.Now().Add(-2 * time.Second))), }, } metav1.SetMetaDataLabel(&obj.ObjectMeta, "alpha.sharding.timebertt.dev/controllerring", "foo") objOld = obj.DeepCopy() }) Describe("#IsShardLease", func() { BeforeEach(func() { p = IsShardLease() }) It("should ignore other object kinds", func() { pod := &corev1.Pod{} Expect(p.Create(event.CreateEvent{Object: pod})).To(BeFalse()) Expect(p.Update(event.UpdateEvent{ObjectOld: pod, ObjectNew: pod})).To(BeFalse()) Expect(p.Delete(event.DeleteEvent{Object: pod})).To(BeFalse()) }) It("should ignore leases without label", func() { delete(obj.Labels, "alpha.sharding.timebertt.dev/controllerring") objOld = obj.DeepCopy() Expect(p.Create(event.CreateEvent{Object: obj})).To(BeFalse()) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeFalse()) }) It("should ignore leases with empty label", func() { metav1.SetMetaDataLabel(&obj.ObjectMeta, "alpha.sharding.timebertt.dev/controllerring", "") objOld = obj.DeepCopy() Expect(p.Create(event.CreateEvent{Object: obj})).To(BeFalse()) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeFalse()) }) It("should react on lease events with label", func() { Expect(p.Create(event.CreateEvent{Object: obj})).To(BeTrue()) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeTrue()) }) }) Describe("#ShardLeaseStateChanged", func() { BeforeEach(func() { p = ShardLeaseStateChanged(fakeClock) }) It("should react on all create events", func() { Expect(p.Create(event.CreateEvent{})).To(BeTrue()) }) It("should react on all delete events", func() { Expect(p.Delete(event.DeleteEvent{})).To(BeTrue()) }) It("should ignore other object kinds on update events", func() { pod := &corev1.Pod{} Expect(p.Update(event.UpdateEvent{ObjectOld: pod, ObjectNew: pod})).To(BeFalse()) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: pod})).To(BeFalse()) }) It("should react when shard state changed to dead (lease released)", func() { obj.Spec.HolderIdentity = nil Expect(leases.ToState(objOld, fakeClock.Now())).To(Equal(leases.Ready)) Expect(leases.ToState(obj, fakeClock.Now())).To(Equal(leases.Dead)) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) }) It("should react when shard state changed to ready (renewed after expired)", func() { objOld.Spec.RenewTime = ptr.To(metav1.NewMicroTime(fakeClock.Now().Add(-time.Duration(*obj.Spec.LeaseDurationSeconds+1) * time.Second))) Expect(leases.ToState(objOld, fakeClock.Now())).To(Equal(leases.Expired)) Expect(leases.ToState(obj, fakeClock.Now())).To(Equal(leases.Ready)) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) }) It("should ignore when shard state hasn't changed", func() { Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) obj.Spec.HolderIdentity = nil objOld.Spec.HolderIdentity = nil Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) }) }) Describe("#ShardLeaseAvailabilityChanged", func() { BeforeEach(func() { p = ShardLeaseAvailabilityChanged(fakeClock) }) It("should react on create events if shard is available", func() { Expect(leases.ToState(obj, fakeClock.Now())).To(Equal(leases.Ready)) Expect(p.Create(event.CreateEvent{Object: obj})).To(BeTrue()) }) It("should ignore create events if shard is not available", func() { obj.Spec.HolderIdentity = nil Expect(leases.ToState(obj, fakeClock.Now())).To(Equal(leases.Dead)) Expect(p.Create(event.CreateEvent{Object: obj})).To(BeFalse()) }) It("should react on delete events if shard was available", func() { Expect(leases.ToState(obj, fakeClock.Now())).To(Equal(leases.Ready)) Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeTrue()) }) It("should ignore delete events if shard was not available", func() { obj.Spec.HolderIdentity = nil Expect(leases.ToState(obj, fakeClock.Now())).To(Equal(leases.Dead)) Expect(p.Delete(event.DeleteEvent{Object: obj})).To(BeFalse()) }) It("should ignore other object kinds", func() { pod := &corev1.Pod{} Expect(p.Create(event.CreateEvent{Object: pod})).To(BeFalse()) Expect(p.Update(event.UpdateEvent{ObjectOld: pod, ObjectNew: pod})).To(BeFalse()) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: pod})).To(BeFalse()) Expect(p.Delete(event.DeleteEvent{Object: pod})).To(BeFalse()) }) It("should react when shard state changed to dead (lease released)", func() { obj.Spec.HolderIdentity = nil Expect(leases.ToState(objOld, fakeClock.Now())).To(Equal(leases.Ready)) Expect(leases.ToState(obj, fakeClock.Now())).To(Equal(leases.Dead)) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) }) It("should ignore when shard state changed to ready (renewed after expired)", func() { objOld.Spec.RenewTime = ptr.To(metav1.NewMicroTime(fakeClock.Now().Add(-time.Duration(*obj.Spec.LeaseDurationSeconds+1) * time.Second))) Expect(leases.ToState(objOld, fakeClock.Now())).To(Equal(leases.Expired)) Expect(leases.ToState(obj, fakeClock.Now())).To(Equal(leases.Ready)) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) }) It("should react when shard state changed to ready (renewed after dead)", func() { objOld.Spec.HolderIdentity = nil Expect(leases.ToState(objOld, fakeClock.Now())).To(Equal(leases.Dead)) Expect(leases.ToState(obj, fakeClock.Now())).To(Equal(leases.Ready)) Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeTrue()) }) It("should ignore when shard state hasn't changed", func() { Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) obj.Spec.HolderIdentity = nil objOld.Spec.HolderIdentity = nil Expect(p.Update(event.UpdateEvent{ObjectOld: objOld, ObjectNew: obj})).To(BeFalse()) }) It("should react if final delete state is unknown even if lease was unavailable", func() { obj.Spec.HolderIdentity = nil Expect(p.Delete(event.DeleteEvent{Object: obj, DeleteStateUnknown: true})).To(BeTrue()) }) }) }) ================================================ FILE: pkg/sharding/predicate/predicate_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package predicate_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestPredicate(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Sharding Predicates Suite") } ================================================ FILE: pkg/sharding/ring/ring.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package ring import ( "time" coordinationv1 "k8s.io/api/coordination/v1" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" shardingmetrics "github.com/timebertt/kubernetes-controller-sharding/pkg/metrics" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/consistenthash" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/leases" ) // FromLeases creates a ring from the given membership information (shard leases). It transforms shard leases into a // usable form, i.e., a hash ring and leases.Shards. // This is a central function in the sharding implementation bringing together the leases package with the // consistenthash package. // In short, it determines the subset of available shards and constructs a new consistenthash.Ring with it. func FromLeases(controllerRing *shardingv1alpha1.ControllerRing, leaseList *coordinationv1.LeaseList, now time.Time) (*consistenthash.Ring, leases.Shards) { // determine ready shards and calculate hash ring shards := leases.ToShards(leaseList.Items, now) availableShards := shards.AvailableShards().IDs() ring := consistenthash.New(nil, 0, availableShards...) shardingmetrics.RingCalculationsTotal.WithLabelValues(controllerRing.Name).Inc() return ring, shards } ================================================ FILE: pkg/sharding/ring/ring_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package ring_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestRing(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Sharding Ring Suite") } ================================================ FILE: pkg/sharding/ring/ring_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package ring_test import ( "strconv" "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/utils/ptr" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/consistenthash" . "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/ring" ) var _ = Describe("FromLeases", func() { var ( now time.Time controllerRing *shardingv1alpha1.ControllerRing leaseList *coordinationv1.LeaseList ) BeforeEach(func() { now = time.Now() controllerRing = &shardingv1alpha1.ControllerRing{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} leaseList = &coordinationv1.LeaseList{} leaseTemplate := &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: "foo-0", }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To("foo-0"), LeaseDurationSeconds: ptr.To[int32](10), AcquireTime: ptr.To(metav1.NewMicroTime(now.Add(-5 * time.Minute))), RenewTime: ptr.To(metav1.NewMicroTime(now.Add(-2 * time.Second))), }, } lease := leaseTemplate.DeepCopy() leaseList.Items = append(leaseList.Items, *lease) lease = leaseTemplate.DeepCopy() lease.Name = "foo-1" lease.Spec.HolderIdentity = ptr.To("foo-1") leaseList.Items = append(leaseList.Items, *lease) lease = leaseTemplate.DeepCopy() lease.Name = "foo-2" lease.Spec.HolderIdentity = nil leaseList.Items = append(leaseList.Items, *lease) lease = leaseTemplate.DeepCopy() lease.Name = "foo-3" lease.Spec.RenewTime = ptr.To(metav1.NewMicroTime(now.Add(-time.Minute))) leaseList.Items = append(leaseList.Items, *lease) }) It("should create a ring from the available shards", func() { ring, shards := FromLeases(controllerRing, leaseList, now) Expect(ring).NotTo(BeNil()) Expect(shards).To(HaveLen(4)) Expect(shards.AvailableShards().IDs()).To(ConsistOf("foo-0", "foo-1")) Expect(probeRingNodes(ring)).To(ConsistOf("foo-0", "foo-1")) }) }) func probeRingNodes(ring *consistenthash.Ring) []string { nodes := sets.New[string]() for i := 0; i < 1000; i++ { nodes.Insert(ring.Hash(strconv.Itoa(i))) } return nodes.UnsortedList() } ================================================ FILE: pkg/utils/client/client_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package client_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestClient(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Client Utils Suite") } ================================================ FILE: pkg/utils/client/options.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package client import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) // ResourceVersion is a client.GetOption and client.ListOption that sets the resourceVersion query parameter. // See https://kubernetes.io/docs/reference/using-api/api-concepts/#the-resourceversion-parameter // Note: this doesn't take effect if there's a later option that overwrites the Raw field (e.g. ListOptions with Raw // set). type ResourceVersion string func (r ResourceVersion) ApplyToGet(opts *client.GetOptions) { if opts.Raw == nil { opts.Raw = &metav1.GetOptions{} } opts.Raw.ResourceVersion = string(r) } func (r ResourceVersion) ApplyToList(opts *client.ListOptions) { if opts.Raw == nil { opts.Raw = &metav1.ListOptions{} } opts.Raw.ResourceVersion = string(r) } ================================================ FILE: pkg/utils/client/options_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package client_test import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "sigs.k8s.io/controller-runtime/pkg/client" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/client" ) var _ = Describe("ResourceVersion", func() { It("should set the resourceVersion on GetOptions", func() { opts := &client.GetOptions{} opts.ApplyOptions([]client.GetOption{ResourceVersion("1")}) Expect(opts.Raw.ResourceVersion).To(Equal("1")) }) It("should set the resourceVersion on ListOptions", func() { opts := &client.ListOptions{} opts.ApplyOptions([]client.ListOption{ResourceVersion("1")}) Expect(opts.Raw.ResourceVersion).To(Equal("1")) }) }) ================================================ FILE: pkg/utils/client/scheme.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package client import ( "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" configv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/config/v1alpha1" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" ) // SharderScheme is the scheme that the sharder uses. var SharderScheme = runtime.NewScheme() func init() { schemeBuilder := runtime.NewSchemeBuilder( clientgoscheme.AddToScheme, shardingv1alpha1.AddToScheme, configv1alpha1.AddToScheme, ) utilruntime.Must(schemeBuilder.AddToScheme(SharderScheme)) } ================================================ FILE: pkg/utils/errors/errors_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package errors_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestErrors(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Errors Utils Suite") } ================================================ FILE: pkg/utils/errors/multi.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package errors import ( "fmt" "strings" ) // FormatErrors is like multierror.ListFormatFunc without the noisy newlines and tabs. // It also simplifies the format for a single error. func FormatErrors(es []error) string { if len(es) == 1 { return es[0].Error() } errs := make([]string, len(es)) for i, err := range es { errs[i] = err.Error() } return fmt.Sprintf("%d errors occurred: %s", len(es), strings.Join(errs, ", ")) } ================================================ FILE: pkg/utils/errors/multi_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package errors_test import ( "fmt" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/errors" ) var _ = Describe("FormatErrors", func() { It("should return the single error", func() { Expect(FormatErrors([]error{fmt.Errorf("foo")})).To(Equal("foo")) }) It("should return the error count and comma separated error list", func() { Expect( FormatErrors([]error{fmt.Errorf("foo"), fmt.Errorf("bar")}), ).To( Equal("2 errors occurred: foo, bar"), ) }) }) ================================================ FILE: pkg/utils/healthz/cache.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package healthz import ( "context" "fmt" "net/http" "time" "sigs.k8s.io/controller-runtime/pkg/healthz" ) type cacheSyncWaiter interface { WaitForCacheSync(ctx context.Context) bool } // CacheSync returns a new healthz.Checker that will pass if all informers in the given cacheSyncWaiter have synced. func CacheSync(cacheSyncWaiter cacheSyncWaiter) healthz.Checker { return func(_ *http.Request) error { // cache.Cache.WaitForCacheSync is racy for a closed context, so use context with 5ms timeout instead. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) defer cancel() if !cacheSyncWaiter.WaitForCacheSync(ctx) { return fmt.Errorf("informers have not synced yet") } return nil } } ================================================ FILE: pkg/utils/healthz/cache_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package healthz_test import ( "context" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/healthz" ) var _ = Describe("CacheSync", func() { It("should succeed if all informers sync", func() { checker := CacheSync(fakeSyncWaiter(true)) Expect(checker(nil)).NotTo(HaveOccurred()) }) It("should fail if informers don't sync", func() { checker := CacheSync(fakeSyncWaiter(false)) Expect(checker(nil)).To(MatchError(ContainSubstring("not synced"))) }) }) type fakeSyncWaiter bool func (f fakeSyncWaiter) WaitForCacheSync(_ context.Context) bool { return bool(f) } ================================================ FILE: pkg/utils/healthz/healthz_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package healthz_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestHealthz(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Healthz Suite") } ================================================ FILE: pkg/utils/pager/pager.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package pager import ( "context" "fmt" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) const ( defaultPageSize = 500 defaultPageBufferSize = 10 ) // lister is the subset of client.Reader that ListPager uses. type lister interface { List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error } // New creates a new pager from the provided reader using the default options. func New(reader lister) *ListPager { return &ListPager{ Reader: reader, PageSize: defaultPageSize, PageBufferSize: defaultPageBufferSize, } } // ListPager assists client code in breaking large list queries into multiple smaller chunks of PageSize or smaller. // The pager does not alter any fields on the initial options list except Continue. // It is implemented like client-go's pager but uses a controller-runtime client, // see https://github.com/kubernetes/client-go/blob/release-1.28/tools/pager/pager.go. // Exception: this ListPager also fixes the `specifying resource version is not allowed when using continue` error // in EachListItem and EachListItemWithAlloc. type ListPager struct { Reader lister // PageSize is the maximum number of objects to retrieve in individual list calls. // If a client.Limit option is passed, the pager uses the option's value instead. PageSize int64 // Number of pages to buffer in EachListItem and EachListItemWithAlloc. PageBufferSize int32 } // EachListItem fetches runtime.Object items using this ListPager and invokes fn on each item. If // fn returns an error, processing stops and that error is returned. If fn does not return an error, // any error encountered while retrieving the list from the server is returned. If the context // cancels or times out, the context error is returned. Since the list is retrieved in paginated // chunks, an "Expired" error (metav1.StatusReasonExpired) may be returned if the pagination list // requests exceed the expiration limit of the apiserver being called. // // Items are retrieved in chunks from the server to reduce the impact on the server with up to // ListPager.PageBufferSize chunks buffered concurrently in the background. // // If items passed to fn are retained for different durations, and you want to avoid // retaining the whole slice returned by p.Reader.List as long as any item is referenced, // use EachListItemWithAlloc instead. func (p *ListPager) EachListItem(ctx context.Context, list client.ObjectList, fn func(obj client.Object) error, opts ...client.ListOption) error { return p.eachListChunkBuffered(ctx, list, func(list client.ObjectList) error { return meta.EachListItem(list, func(obj runtime.Object) error { return fn(obj.(client.Object)) }) }, opts...) } // EachListItemWithAlloc works like EachListItem, but avoids retaining references to the items slice returned by p.Reader.List. // It does this by making a shallow copy of non-pointer items in the slice returned by p.Reader.List. // // If the items passed to fn are not retained, or are retained for the same duration, use EachListItem instead for memory efficiency. func (p *ListPager) EachListItemWithAlloc(ctx context.Context, list client.ObjectList, fn func(obj client.Object) error, opts ...client.ListOption) error { return p.eachListChunkBuffered(ctx, list, func(list client.ObjectList) error { return meta.EachListItemWithAlloc(list, func(obj runtime.Object) error { return fn(obj.(client.Object)) }) }, opts...) } // eachListChunkBuffered fetches runtimeObject list chunks using this ListPager and invokes fn on // each list chunk. If fn returns an error, processing stops and that error is returned. If fn does // not return an error, any error encountered while retrieving the list from the server is // returned. If the context cancels or times out, the context error is returned. Since the list is // retrieved in paginated chunks, an "Expired" error (metav1.StatusReasonExpired) may be returned if // the pagination list requests exceed the expiration limit of the apiserver being called. // // Up to ListPager.PageBufferSize chunks are buffered concurrently in the background. func (p *ListPager) eachListChunkBuffered(ctx context.Context, list client.ObjectList, fn func(list client.ObjectList) error, opts ...client.ListOption) error { if p.PageBufferSize < 0 { return fmt.Errorf("ListPager.PageBufferSize must be >= 0, got %d", p.PageBufferSize) } // Ensure background goroutine is stopped if this call exits before all list items are // processed. Cancellation error from this deferred cancel call is never returned to caller; // either the list result has already been sent to bgResultC or the fn error is returned and // the cancellation error is discarded. ctx, cancel := context.WithCancel(ctx) defer cancel() chunkC := make(chan client.ObjectList, p.PageBufferSize) bgResultC := make(chan error, 1) go func() { defer utilruntime.HandleCrash() var err error defer func() { close(chunkC) bgResultC <- err }() err = p.eachListChunk(ctx, list, func(chunk client.ObjectList) error { select { case chunkC <- chunk: // buffer the chunk, this can block case <-ctx.Done(): return ctx.Err() } return nil }, opts...) }() for o := range chunkC { select { case <-ctx.Done(): return ctx.Err() default: } err := fn(o) if err != nil { return err // any fn error should be returned immediately } } // promote the results of our background goroutine to the foreground return <-bgResultC } // eachListChunk fetches runtimeObject list chunks using this ListPager and invokes fn on each list // chunk. If fn returns an error, processing stops and that error is returned. If fn does not return // an error, any error encountered while retrieving the list from the server is returned. If the // context cancels or times out, the context error is returned. Since the list is retrieved in // paginated chunks, an "Expired" error (metav1.StatusReasonExpired) may be returned if the // pagination list requests exceed the expiration limit of the apiserver being called. func (p *ListPager) eachListChunk(ctx context.Context, list client.ObjectList, fn func(list client.ObjectList) error, opts ...client.ListOption) error { options := &client.ListOptions{} options.ApplyOptions(opts) if options.Limit == 0 { options.Limit = p.PageSize } if options.Limit < 0 { return fmt.Errorf("ListPager.PageSize must be >= 0, got %d", options.Limit) } for { select { case <-ctx.Done(): return ctx.Err() default: } // create a new list to not share memory between paginated lists list = list.DeepCopyObject().(client.ObjectList) if err := p.Reader.List(ctx, list, options); err != nil { return err } if err := fn(list); err != nil { return err } // if we have no more items, return. if len(list.GetContinue()) == 0 { return nil } // set the next loop up options.Continue = list.GetContinue() // Clear the ResourceVersion(Match) on the subsequent List calls to avoid the // `specifying resource version is not allowed when using continue` error. // See https://github.com/kubernetes/kubernetes/issues/85221#issuecomment-553748143. if options.Raw == nil { options.Raw = &metav1.ListOptions{} } options.Raw.ResourceVersion = "" options.Raw.ResourceVersionMatch = "" } } ================================================ FILE: pkg/utils/pager/pager_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package pager_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestPager(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Pager Suite") } ================================================ FILE: pkg/utils/pager/pager_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package pager_test import ( "context" "fmt" "strconv" "sync" "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" gomegatypes "github.com/onsi/gomega/types" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/pager" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) var _ = Describe("ListPager", func() { const ( pageSize = 2 pageCount = 5 objectCount = 9 ) var ( ctx context.Context allPods []corev1.Pod reader *lister pager *ListPager ) BeforeEach(func() { ctx = context.Background() allPods = podSlice(0, objectCount) reader = &lister{allPods: allPods} pager = New(reader) pager.PageSize = pageSize pager.PageBufferSize = 2 }) It("should page all objects", func() { var pods []*corev1.Pod Expect(pager.EachListItem(ctx, &corev1.PodList{}, func(obj client.Object) error { pods = append(pods, obj.(*corev1.Pod)) return nil })).To(Succeed()) Expect(pods).To(havePods(1, objectCount)) Expect(reader.calls).To(Equal(pageCount)) }) It("should page objects with the custom limit", func() { var pods []client.Object i := 0 Expect(pager.EachListItem(ctx, &corev1.PodList{}, func(obj client.Object) error { if obj != &allPods[i] { return fmt.Errorf("the pager should reuse the object") } i++ pods = append(pods, obj) return nil }, client.Limit(objectCount+1))).To(Succeed()) Expect(pods).To(havePods(1, objectCount)) Expect(reader.calls).To(Equal(1)) }) It("should fail due to negative page size", func() { pager.PageSize = -1 Expect(pager.EachListItem(ctx, &corev1.PodList{}, func(obj client.Object) error { return nil })).To(MatchError(ContainSubstring("PageSize must be >= 0"))) }) It("should fail due to negative page buffer size", func() { pager.PageBufferSize = -1 Expect(pager.EachListItem(ctx, &corev1.PodList{}, func(obj client.Object) error { return nil })).To(MatchError(ContainSubstring("PageBufferSize must be >= 0"))) }) It("should return the lister error", func() { Expect(pager.EachListItem(ctx, &corev1.ConfigMapList{}, func(obj client.Object) error { return nil })).To(MatchError("expected *corev1.PodList, got *v1.ConfigMapList")) }) It("should return the iterator error", func() { Expect(pager.EachListItem(ctx, &corev1.PodList{}, func(obj client.Object) error { if obj.GetName() == "pod-5" { return fmt.Errorf("foo") } return nil })).To(MatchError("foo")) }) It("should cancel the operation when the context is canceled", func(specCtx SpecContext) { done := make(chan struct{}) blockConsumer := make(chan struct{}) defer close(blockConsumer) ctx, cancel := context.WithCancel(specCtx) go func() { defer GinkgoRecover() Expect(pager.EachListItem(ctx, &corev1.PodList{}, func(obj client.Object) error { <-blockConsumer return nil })).To(MatchError(context.Canceled)) close(done) }() cancel() Eventually(specCtx, done).Should(BeClosed()) }, SpecTimeout(time.Second)) It("should buffer the configured number of pages", func(specCtx SpecContext) { done := make(chan struct{}) ctx, cancel := context.WithCancel(specCtx) go func() { defer GinkgoRecover() Expect(pager.EachListItem(ctx, &corev1.PodList{}, func(obj client.Object) error { <-ctx.Done() return nil })).To(MatchError(context.Canceled)) close(done) }() // consumer takes one chunk out and one chunk is produced but blocked, // so we have made PageBufferSize + 2 calls to the lister Eventually(specCtx, reader.getCalls).Should(BeEquivalentTo(pager.PageBufferSize + 2)) cancel() Eventually(specCtx, done).Should(BeClosed()) }, SpecTimeout(time.Second)) It("should correctly handle the resourceVersion fields", func() { Expect(pager.EachListItem(ctx, &corev1.PodList{}, func(obj client.Object) error { return nil }, &client.ListOptions{Raw: &metav1.ListOptions{ ResourceVersion: "0", ResourceVersionMatch: "NotOlderThan", }})).To(Succeed()) }) Describe("#EachListItemWithAlloc", func() { It("should page all objects", func() { var pods []client.Object i := 0 Expect(pager.EachListItemWithAlloc(ctx, &corev1.PodList{}, func(obj client.Object) error { if obj == &allPods[i] { return fmt.Errorf("the pager should copy the object") } i++ pods = append(pods, obj) return nil })).To(Succeed()) Expect(pods).To(havePods(1, objectCount)) Expect(reader.calls).To(Equal(pageCount)) }) }) }) type lister struct { mu sync.Mutex calls int allPods []corev1.Pod previousList client.ObjectList } func (l *lister) List(_ context.Context, list client.ObjectList, opts ...client.ListOption) error { func() { l.mu.Lock() defer l.mu.Unlock() l.calls++ }() if list == l.previousList { return fmt.Errorf("the pager should not reuse the list for multiple calls") } l.previousList = list podList, ok := list.(*corev1.PodList) if !ok { return fmt.Errorf("expected *corev1.PodList, got %T", list) } listOptions := &client.ListOptions{} listOptions.ApplyOptions(opts) if l.calls > 1 { if listOptions.Raw.ResourceVersion != "" { return fmt.Errorf("the pager should reset the resourceVersion field for consecutive calls") } if listOptions.Raw.ResourceVersionMatch != "" { return fmt.Errorf("the pager should reset the resourceVersionMatch field for consecutive calls") } } limit := listOptions.Limit if limit == 0 { return fmt.Errorf("the pager should set limit") } var offset int64 if listOptions.Continue != "" { var err error offset, err = strconv.ParseInt(listOptions.Continue, 10, 64) if err != nil { return err } } defer func() { if offset+limit >= int64(len(l.allPods)) { podList.Continue = "" } else { podList.Continue = strconv.FormatInt(offset+int64(len(podList.Items)), 10) } }() podList.Items = l.allPods[offset:min(int64(len(l.allPods)), offset+limit)] return nil } func (l *lister) getCalls() int { l.mu.Lock() defer l.mu.Unlock() return l.calls } func podSlice(offset, n int64) []corev1.Pod { pods := make([]corev1.Pod, n) for i := int64(0); i < n; i++ { pods[i] = corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod-" + strconv.FormatInt(offset+i+1, 10)}} } return pods } func havePods(i, j int) gomegatypes.GomegaMatcher { var matchers []any for ; i <= j; i++ { matchers = append(matchers, HaveName("pod-"+strconv.Itoa(i))) } return HaveExactElements(matchers...) } ================================================ FILE: pkg/utils/routes/profiling.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package routes import ( "net/http" "net/http/pprof" ) // ProfilingHandlers is the set of profiling endpoints. // This can be added to controller-runtime's metrics server via manager.Options.Metrics.ExtraHandlers. var ProfilingHandlers = map[string]http.Handler{ "/debug/pprof": http.RedirectHandler("/debug/pprof/", http.StatusFound), "/debug/pprof/": http.HandlerFunc(pprof.Index), "/debug/pprof/profile": http.HandlerFunc(pprof.Profile), "/debug/pprof/symbol": http.HandlerFunc(pprof.Symbol), "/debug/pprof/trace": http.HandlerFunc(pprof.Trace), } ================================================ FILE: pkg/utils/strings.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package utils import ( "unicode" ) // CapitalizeFirst capitalizes the first letter in the given string. func CapitalizeFirst(in string) string { r := []rune(in) r[0] = unicode.ToUpper(r[0]) return string(r) } ================================================ FILE: pkg/utils/strings_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package utils_test import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils" ) var _ = Describe("CapitalizeFirst", func() { It("should capitalize the first letter", func() { Expect(CapitalizeFirst("foo bar Baz")).To(Equal("Foo bar Baz")) Expect(CapitalizeFirst("Foo BAR Baz")).To(Equal("Foo BAR Baz")) Expect(CapitalizeFirst("FOO bar Baz")).To(Equal("FOO bar Baz")) }) }) ================================================ FILE: pkg/utils/test/envtest.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package test import ( "os" "strings" ) // UseExistingCluster reads the `USE_EXISTING_CLUSTER` env var similar to what envtest does, though exported. func UseExistingCluster() bool { return strings.ToLower(os.Getenv("USE_EXISTING_CLUSTER")) == "true" } ================================================ FILE: pkg/utils/test/matchers/condition.go ================================================ /* Copyright 2024 Tim Ebert. 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. */ package matchers import ( . "github.com/onsi/gomega" gomegatypes "github.com/onsi/gomega/types" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // MatchCondition is an alias for gomega.And to make matching conditions more readable, e.g., // // Expect(controllerRing.Status.Conditions).To(ConsistOf( // MatchCondition( // OfType(shardingv1alpha1.ControllerRingReady), // WithStatus(metav1.ConditionTrue), // ), // )) var MatchCondition = And // OfType returns a matcher for checking whether a condition has a certain type. func OfType(conditionType string) gomegatypes.GomegaMatcher { return HaveField("Type", Equal(conditionType)) } // WithStatus returns a matcher for checking whether a condition has a certain status. func WithStatus(status metav1.ConditionStatus) gomegatypes.GomegaMatcher { return HaveField("Status", Equal(status)) } // WithReason returns a matcher for checking whether a condition has a certain reason. func WithReason(reason string) gomegatypes.GomegaMatcher { return HaveField("Reason", Equal(reason)) } // WithMessage returns a matcher for checking whether a condition has a certain message. func WithMessage(message string) gomegatypes.GomegaMatcher { return HaveField("Message", ContainSubstring(message)) } ================================================ FILE: pkg/utils/test/matchers/errors.go ================================================ /* Copyright 2024 Tim Ebert. 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. */ package matchers import ( "fmt" "github.com/onsi/gomega/format" ) type errorMatcher struct { match func(error) bool message string } func (k *errorMatcher) Match(actual interface{}) (success bool, err error) { if actual == nil { return false, nil } actualErr, actualOk := actual.(error) if !actualOk { return false, fmt.Errorf("expected an error, got:\n%s", format.Object(actual, 1)) } return k.match(actualErr), nil } func (k *errorMatcher) FailureMessage(actual interface{}) (message string) { return format.Message(actual, fmt.Sprintf("to be %s error", k.message)) } func (k *errorMatcher) NegatedFailureMessage(actual interface{}) (message string) { return format.Message(actual, fmt.Sprintf("to not be %s error", k.message)) } ================================================ FILE: pkg/utils/test/matchers/matchers.go ================================================ /* Copyright 2024 Tim Ebert. 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. */ package matchers import ( "fmt" "reflect" "github.com/onsi/gomega/gcustom" gomegatypes "github.com/onsi/gomega/types" apierrors "k8s.io/apimachinery/pkg/api/errors" ) // BeNotFoundError checks if error is a NotFound error. func BeNotFoundError() gomegatypes.GomegaMatcher { return &errorMatcher{ match: apierrors.IsNotFound, message: "NotFound", } } // BeFunc is a matcher that returns true if expected and actual are the same func. func BeFunc(expected any) gomegatypes.GomegaMatcher { return gcustom.MakeMatcher(func(actual any) (bool, error) { var ( valueExpected = reflect.ValueOf(expected) valueActual = reflect.ValueOf(actual) ) if valueExpected.Kind() != reflect.Func { return false, fmt.Errorf("expected should be a func, got %v", valueExpected.Kind()) } if valueActual.Kind() != reflect.Func { return false, fmt.Errorf("actual should be a func, got %v", valueActual.Kind()) } return valueExpected.Pointer() == valueActual.Pointer(), nil }) } ================================================ FILE: pkg/utils/test/matchers/object.go ================================================ /* Copyright 2024 Tim Ebert. 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. */ package matchers import ( . "github.com/onsi/gomega" gomegatypes "github.com/onsi/gomega/types" ) // HaveName succeeds if the actual object has a matching name. func HaveName(name string) gomegatypes.GomegaMatcher { return HaveField("ObjectMeta.Name", name) } // HaveNames succeeds if the actual list consists of matching names. func HaveNames(names ...string) gomegatypes.GomegaMatcher { matchers := make([]any, len(names)) for i, n := range names { matchers[i] = HaveName(n) } return HaveField("Items", ConsistOf(matchers...)) } // HaveLabel succeeds if the actual object has a label with a matching key. func HaveLabel(key any) gomegatypes.GomegaMatcher { return HaveField("ObjectMeta.Labels", HaveKey(key)) } // HaveLabelWithValue succeeds if the actual object has a label with a matching key and value. func HaveLabelWithValue(key, value any) gomegatypes.GomegaMatcher { return HaveField("ObjectMeta.Labels", HaveKeyWithValue(key, value)) } ================================================ FILE: pkg/utils/test/object.go ================================================ /* Copyright 2024 Tim Ebert. 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. */ package test import ( "crypto/sha256" "encoding/hex" "github.com/google/uuid" ) // RandomSuffix generates a random string that is safe to use as a name suffix in tests. func RandomSuffix() string { unique := uuid.New() hash := sha256.Sum256(unique[:]) return hex.EncodeToString(hash[:])[:8] } ================================================ FILE: pkg/utils/test/paths.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package test import ( "os" "path/filepath" utilruntime "k8s.io/apimachinery/pkg/util/runtime" ) // RepoRoot returns a relative path from the current working directory to the repository root. For use in tests only. func RepoRoot() string { relativePath := "." dir, err := os.Getwd() utilruntime.Must(err) for dir != "/" { if _, err := os.Stat(filepath.Join(dir, "go.work")); err == nil { break } else if !os.IsNotExist(err) { panic(err) } // navigate one directory up, build up relative path dir = filepath.Dir(dir) relativePath = filepath.Join(relativePath, "..") } return filepath.Clean(relativePath) } // PathShardingCRDs returns the path to the directory containing the sharding CRDs. For use in tests only. func PathShardingCRDs() string { return filepath.Join(RepoRoot(), "config", "crds") } ================================================ FILE: pkg/utils/utils_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package utils_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestUtils(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Utils Suite") } ================================================ FILE: pkg/webhook/add.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package webhook import ( "context" "fmt" "sigs.k8s.io/controller-runtime/pkg/manager" configv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/config/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/webhook/sharder" ) // AddToManager adds all webhooks to the manager. func AddToManager(ctx context.Context, mgr manager.Manager, config *configv1alpha1.SharderConfig) error { if err := (&sharder.Handler{}).AddToManager(mgr); err != nil { return fmt.Errorf("failed adding sharder webhook: %w", err) } return nil } ================================================ FILE: pkg/webhook/sharder/add.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package sharder import ( "context" "fmt" "net/http" "path" "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/clock" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" ) // webhookPathPrefix is the path prefix at which the handler should be registered. const webhookPathPrefix = "/webhooks/sharder/controllerring/" // AddToManager adds Handler to the given manager. func (h *Handler) AddToManager(mgr manager.Manager) error { if h.Reader == nil { h.Reader = mgr.GetCache() } if h.Clock == nil { h.Clock = clock.RealClock{} } if h.Metrics == nil { h.Metrics = realMetrics{} } mgr.GetWebhookServer().Register(webhookPathPrefix, &admission.Webhook{ Handler: h, WithContextFunc: NewContextWithRequestPath, }) return nil } // WebhookPathForControllerRing returns the webhook handler path that should be used for implementing the given // ControllerRing. It is the reverse of ControllerRingForWebhookPath. func WebhookPathForControllerRing(ring *shardingv1alpha1.ControllerRing) string { return path.Join(webhookPathPrefix, ring.Name) } // ControllerRingForWebhookPath returns the ControllerRing that is associated with the given webhook handler path. // It is the reverse of WebhookPathForControllerRing. func ControllerRingForWebhookPath(requestPath string) (*shardingv1alpha1.ControllerRing, error) { if !strings.HasPrefix(requestPath, webhookPathPrefix) { return nil, fmt.Errorf("unexpected request path: %s", requestPath) } name := strings.TrimPrefix(requestPath, webhookPathPrefix) if name == "" { return nil, fmt.Errorf("unexpected request path: %s", requestPath) } return &shardingv1alpha1.ControllerRing{ObjectMeta: metav1.ObjectMeta{Name: name}}, nil } type ctxKey int // keyRequestPath is used for storing the admission request's path in contexts. const keyRequestPath ctxKey = 0 // NewContextWithRequestPath augments the given context with the request's path. func NewContextWithRequestPath(ctx context.Context, r *http.Request) context.Context { return context.WithValue(ctx, keyRequestPath, r.URL.Path) } // RequestPathFromContext returns the request's path stored in the given context. func RequestPathFromContext(ctx context.Context) (string, error) { if v, ok := ctx.Value(keyRequestPath).(string); ok { return v, nil } return "", fmt.Errorf("no request path found in context") } ================================================ FILE: pkg/webhook/sharder/add_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package sharder_test import ( "context" "net/http" "net/url" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" . "github.com/timebertt/kubernetes-controller-sharding/pkg/webhook/sharder" ) var _ = Describe("webhook path", func() { const controllerRingName = "foo" Describe("#WebhookPathForControllerRing", func() { It("should return the correct webhook path", func() { controllerRing := &shardingv1alpha1.ControllerRing{ObjectMeta: metav1.ObjectMeta{Name: controllerRingName}} Expect(WebhookPathForControllerRing(controllerRing)).To(Equal("/webhooks/sharder/controllerring/" + controllerRingName)) }) }) Describe("#ControllerRingForWebhookPath", func() { It("should return an error for invalid paths", func() { matchError := MatchError(ContainSubstring("unexpected request path")) Expect(ControllerRingForWebhookPath("/foo")).Error().To(matchError) Expect(ControllerRingForWebhookPath("/webhooks")).Error().To(matchError) Expect(ControllerRingForWebhookPath("/webhooks/sharder")).Error().To(matchError) Expect(ControllerRingForWebhookPath("/webhooks/sharder/controllerring")).Error().To(matchError) Expect(ControllerRingForWebhookPath("/webhooks/sharder/controllerring/")).Error().To(matchError) }) It("should return a ControllerRing with name", func() { Expect(ControllerRingForWebhookPath("/webhooks/sharder/controllerring/" + controllerRingName)).To( Equal(&shardingv1alpha1.ControllerRing{ ObjectMeta: metav1.ObjectMeta{Name: controllerRingName}, }), ) }) }) }) var _ = Describe("webhook context", func() { It("should inject and extract the request path into/from the context", func() { const path = "/webhooks/sharder/controllerring/foo" ctx := NewContextWithRequestPath(context.Background(), &http.Request{ URL: &url.URL{Path: path}, }) Expect(RequestPathFromContext(ctx)).To(Equal(path)) }) It("should return an error if context doesn't contain path value", func() { Expect(RequestPathFromContext(context.Background())).Error().To(MatchError("no request path found in context")) }) }) ================================================ FILE: pkg/webhook/sharder/handler.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package sharder import ( "context" "fmt" "net/http" "strings" "gomodules.xyz/jsonpatch/v2" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/json" "k8s.io/utils/clock" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/key" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/ring" ) // Handler handles admission requests and invalidates the static token in Secret resources related to ServiceAccounts. type Handler struct { Reader client.Reader Clock clock.PassiveClock Metrics Metrics } func (h *Handler) Handle(ctx context.Context, req admission.Request) admission.Response { log := logf.FromContext(ctx) controllerRing, err := ControllerRingForRequest(ctx, h.Reader) if err != nil { return admission.Errored(http.StatusInternalServerError, fmt.Errorf("error determining ControllerRing for request: %w", err)) } // Unfortunately, admission.Decoder / runtime.Decoder can't handle decoding into PartialObjectMetadata. // We are only interested in the metadata and webhooks always use json encoding, so let's simply decode ourselves. obj := &metav1.PartialObjectMetadata{} if err := json.Unmarshal(req.Object.Raw, obj); err != nil { return admission.Errored(http.StatusInternalServerError, fmt.Errorf("error decoding object: %w", err)) } labelShard := controllerRing.LabelShard() // Don't touch labels that the object already has, we can't simply reassign it because the active shard might still // be working on it. if obj.Labels[labelShard] != "" { return admission.Allowed("object is already assigned") } keyFunc, err := key.FuncForResource(metav1.GroupResource{ Group: req.Resource.Group, Resource: req.Resource.Resource, }, controllerRing) if err != nil { return admission.Errored(http.StatusBadRequest, fmt.Errorf("error determining hash key func for object: %w", err)) } hashKey, err := keyFunc(obj) if err != nil { return admission.Errored(http.StatusBadRequest, fmt.Errorf("error calculating hash key for object: %w", err)) } if hashKey == "" { return admission.Allowed("object should not be assigned") } // collect list of shards in the ring leaseList := &coordinationv1.LeaseList{} if err := h.Reader.List(ctx, leaseList, client.MatchingLabelsSelector{Selector: controllerRing.LeaseSelector()}); err != nil { return admission.Errored(http.StatusInternalServerError, fmt.Errorf("error listing Leases for ControllerRing: %w", err)) } // get ring from cache and hash the object onto the ring hashRing, _ := ring.FromLeases(controllerRing, leaseList, h.Clock.Now()) shard := hashRing.Hash(hashKey) if shard == "" { return admission.Allowed("there is no available shard") } log.V(1).Info("Assigning object for ControllerRing", "controllerRing", client.ObjectKeyFromObject(controllerRing), "shard", shard) patches := make([]jsonpatch.JsonPatchOperation, 0, 2) if obj.Labels == nil { patches = append(patches, jsonpatch.NewOperation("add", "/metadata/labels", map[string]string{})) } // If we reach here, the shard label is always missing. Otherwise, we would have exited early. patches = append(patches, jsonpatch.NewOperation("add", "/metadata/labels/"+rfc6901Encoder.Replace(labelShard), shard)) if !ptr.Deref(req.DryRun, false) { h.Metrics.ObserveAssignment(controllerRing.Name, metav1.GroupResource{Group: req.Resource.Group, Resource: req.Resource.Resource}) } return admission.Patched("assigning object", patches...) } // ControllerRingForRequest returns the Ring object matching the requests' path. func ControllerRingForRequest(ctx context.Context, c client.Reader) (*shardingv1alpha1.ControllerRing, error) { requestPath, err := RequestPathFromContext(ctx) if err != nil { return nil, err } controllerRing, err := ControllerRingForWebhookPath(requestPath) if err != nil { return nil, err } if err := c.Get(ctx, client.ObjectKeyFromObject(controllerRing), controllerRing); err != nil { return nil, fmt.Errorf("error getting ControllerRing: %w", err) } return controllerRing, nil } // rfc6901Encoder can escape / characters in label keys for inclusion in JSON patch paths. var rfc6901Encoder = strings.NewReplacer("~", "~0", "/", "~1") ================================================ FILE: pkg/webhook/sharder/handler_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package sharder_test import ( "context" "net/http" "net/url" "time" jsonpatch "github.com/evanphx/json-patch" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" gomegatypes "github.com/onsi/gomega/types" jsonpatchtypes "gomodules.xyz/jsonpatch/v2" coordinationv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/json" "k8s.io/utils/clock" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" utilclient "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/client" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" . "github.com/timebertt/kubernetes-controller-sharding/pkg/webhook/sharder" ) var _ = Describe("Handler", func() { const controllerRingName = "foo" var ( ctx context.Context handler admission.Handler metrics *fakeMetrics controllerRing *shardingv1alpha1.ControllerRing mainObj *corev1.Secret controlledObj *corev1.ConfigMap availableShard *coordinationv1.Lease fakeClient client.Client ) BeforeEach(func() { controllerRing = &shardingv1alpha1.ControllerRing{ ObjectMeta: metav1.ObjectMeta{ Name: controllerRingName, }, Spec: shardingv1alpha1.ControllerRingSpec{ Resources: []shardingv1alpha1.RingResource{{ GroupResource: metav1.GroupResource{ Resource: "secrets", }, ControlledResources: []metav1.GroupResource{{ Resource: "configmaps", }}, }}, }, } ctx = NewContextWithRequestPath(context.Background(), &http.Request{ URL: &url.URL{Path: "/webhooks/sharder/controllerring/" + controllerRingName}, }) mainObj = &corev1.Secret{ TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Secret"}, ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}, } controlledObj = &corev1.ConfigMap{ TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "ConfigMap"}, ObjectMeta: metav1.ObjectMeta{ Namespace: mainObj.Namespace, OwnerReferences: []metav1.OwnerReference{{ APIVersion: mainObj.APIVersion, Kind: mainObj.Kind, Name: mainObj.Name, Controller: ptr.To(true), }}, }, } fakeClock := &clock.RealClock{} availableShard = &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: "shard-0", Labels: map[string]string{ shardingv1alpha1.LabelControllerRing: controllerRing.Name, }, }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To("shard-0"), LeaseDurationSeconds: ptr.To[int32](10), AcquireTime: ptr.To(metav1.NewMicroTime(fakeClock.Now().Add(-5 * time.Minute))), RenewTime: ptr.To(metav1.NewMicroTime(fakeClock.Now().Add(-2 * time.Second))), }, } fakeClient = fake.NewClientBuilder(). WithScheme(utilclient.SharderScheme). WithObjects(controllerRing, availableShard). Build() metrics = &fakeMetrics{} handler = &Handler{ Reader: fakeClient, Clock: fakeClock, Metrics: metrics, } }) Describe("#ControllerRingForRequest", func() { It("should return the ControllerRing matching the request", func() { Expect(ControllerRingForRequest(ctx, fakeClient)).To(Equal(controllerRing)) }) }) Describe("#Handle", func() { When("the request has an invalid path", func() { BeforeEach(func() { ctx = NewContextWithRequestPath(context.Background(), &http.Request{ URL: &url.URL{Path: "/webhooks/sharder/controllerring/"}, }) }) It("should return an error", func() { Expect(handler.Handle(ctx, newRequest(mainObj))).To(beErrored(ContainSubstring("unexpected request path"))) }) }) When("the request is for a non-existing ControllerRing", func() { BeforeEach(func() { ctx = NewContextWithRequestPath(context.Background(), &http.Request{ URL: &url.URL{Path: "/webhooks/sharder/controllerring/not-existing"}, }) }) It("should return an error", func() { Expect(handler.Handle(ctx, newRequest(mainObj))).To(beErrored(ContainSubstring("error getting ControllerRing"))) }) }) When("the request has an invalid object", func() { It("should return an error", func() { req := admission.Request{} req.Object.Raw = []byte("foo") Expect(handler.Handle(ctx, req)).To(beErrored(ContainSubstring("error decoding object"))) }) }) When("the request has an unrelated object", func() { It("should return an error", func() { Expect(handler.Handle(ctx, newRequest(&corev1.Pod{}))).To(beErrored(ContainSubstring("not found in ControllerRing"))) }) }) When("the main object uses generateName", func() { BeforeEach(func() { mainObj.Name = "" mainObj.GenerateName = "test-" }) It("should return an error", func() { Expect(handler.Handle(ctx, newRequest(mainObj))).To(beErrored(ContainSubstring("generateName is not supported"))) }) }) When("the object is already assigned", func() { BeforeEach(func() { metav1.SetMetaDataLabel(&mainObj.ObjectMeta, controllerRing.LabelShard(), "foo") metav1.SetMetaDataLabel(&controlledObj.ObjectMeta, controllerRing.LabelShard(), "foo") }) It("should do nothing", func() { Expect(handler.Handle(ctx, newRequest(mainObj))).To(beAllowed("object is already assigned")) Expect(handler.Handle(ctx, newRequest(controlledObj))).To(beAllowed("object is already assigned")) }) }) When("there is no available shard", func() { BeforeEach(func() { availableShard.Spec.HolderIdentity = nil Expect(fakeClient.Update(ctx, availableShard)).To(Succeed()) }) It("should do nothing", func() { Expect(handler.Handle(ctx, newRequest(mainObj))).To(beAllowed("there is no available shard")) Expect(handler.Handle(ctx, newRequest(controlledObj))).To(beAllowed("there is no available shard")) }) }) When("the controlled object has no controller reference", func() { BeforeEach(func() { controlledObj.OwnerReferences = nil }) It("should do nothing", func() { Expect(handler.Handle(ctx, newRequest(controlledObj))).To(beAllowed("object should not be assigned")) }) }) When("the object has no labels", func() { It("should add labels and assign the object", func() { res := handler.Handle(ctx, newRequest(mainObj)) Expect(res).To(bePatched()) Expect(applyPatches(mainObj, res.Patches)).To(HaveLabelWithValue(controllerRing.LabelShard(), availableShard.Name)) Expect(metrics.assignments).To(Equal(1)) res = handler.Handle(ctx, newRequest(controlledObj)) Expect(res).To(bePatched()) Expect(applyPatches(controlledObj, res.Patches)).To(HaveLabelWithValue(controllerRing.LabelShard(), availableShard.Name)) Expect(metrics.assignments).To(Equal(2)) }) }) When("the object has other labels", func() { BeforeEach(func() { metav1.SetMetaDataLabel(&mainObj.ObjectMeta, "foo", "bar") metav1.SetMetaDataLabel(&controlledObj.ObjectMeta, "foo", "bar") }) It("should keep existing labels and assign the object", func() { res := handler.Handle(ctx, newRequest(mainObj)) Expect(res).To(bePatched()) Expect(applyPatches(mainObj, res.Patches)).To(And( HaveLabelWithValue("foo", "bar"), HaveLabelWithValue(controllerRing.LabelShard(), availableShard.Name), )) res = handler.Handle(ctx, newRequest(controlledObj)) Expect(res).To(bePatched()) Expect(applyPatches(controlledObj, res.Patches)).To(And( HaveLabelWithValue("foo", "bar"), HaveLabelWithValue(controllerRing.LabelShard(), availableShard.Name), )) }) }) When("the request is dry-run", func() { It("should not observe metrics", func() { req := newRequest(mainObj) req.DryRun = ptr.To(true) Expect(handler.Handle(ctx, req)).To(bePatched()) Expect(metrics.assignments).To(BeZero()) }) }) }) }) func newRequest(obj client.Object) admission.Request { GinkgoHelper() var gvr metav1.GroupVersionResource switch obj.(type) { case *corev1.Secret: gvr = metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"} case *corev1.ConfigMap: gvr = metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "configmaps"} case *corev1.Pod: gvr = metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"} default: Fail("unknown object type") } req := admission.Request{} req.Resource = gvr var err error req.Object.Raw, err = json.Marshal(obj) Expect(err).NotTo(HaveOccurred()) return req } func beAllowed(message any) gomegatypes.GomegaMatcher { return And( HaveField("Patches", BeEmpty()), HaveField("AdmissionResponse", And( HaveField("Allowed", BeTrue()), HaveField("Result.Message", message), )), ) } func bePatched() gomegatypes.GomegaMatcher { return And( HaveField("Patches", Not(BeEmpty())), HaveField("AdmissionResponse", And( HaveField("Allowed", BeTrue()), HaveField("Result.Message", "assigning object"), )), ) } func beErrored(message any) gomegatypes.GomegaMatcher { return And( HaveField("Patches", BeEmpty()), HaveField("AdmissionResponse", And( HaveField("Allowed", BeFalse()), HaveField("Result.Message", message), )), ) } func applyPatches[T client.Object](obj T, patches []jsonpatchtypes.Operation) T { GinkgoHelper() rawObj, err := json.Marshal(obj) Expect(err).NotTo(HaveOccurred()) rawPatch, err := json.Marshal(patches) Expect(err).NotTo(HaveOccurred()) patch, err := jsonpatch.DecodePatch(rawPatch) Expect(err).NotTo(HaveOccurred()) rawPatchedObj, err := patch.Apply(rawObj) Expect(err).NotTo(HaveOccurred()) patchedObj := obj.DeepCopyObject().(T) Expect(json.Unmarshal(rawPatchedObj, patchedObj)).To(Succeed()) return patchedObj } type fakeMetrics struct { assignments int } func (f *fakeMetrics) ObserveAssignment(string, metav1.GroupResource) { f.assignments++ } ================================================ FILE: pkg/webhook/sharder/metrics.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package sharder import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" shardingmetrics "github.com/timebertt/kubernetes-controller-sharding/pkg/metrics" ) type Metrics interface { ObserveAssignment(controllerRingName string, gr metav1.GroupResource) } type realMetrics struct{} func (realMetrics) ObserveAssignment(controllerRingName string, gr metav1.GroupResource) { shardingmetrics.AssignmentsTotal.WithLabelValues(controllerRingName, gr.Group, gr.Resource).Inc() } ================================================ FILE: pkg/webhook/sharder/sharder_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package sharder_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestSharder(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Sharder Webhook Suite") } ================================================ FILE: test/e2e/checksum_controller_test.go ================================================ /* Copyright 2024 Tim Ebert. 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. */ package e2e import ( "context" "fmt" "maps" "strconv" "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" appsv1 "k8s.io/api/apps/v1" autoscalingv1 "k8s.io/api/autoscaling/v1" coordinationv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" . "sigs.k8s.io/controller-runtime/pkg/envtest/komega" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/leases" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) const ( checksumControllerName = "checksum-controller" namePrefixChecksums = "checksums-" objectCount = 100 ) var _ = Describe("Checksum Controller", Label(checksumControllerName), func() { Describe("setup", Ordered, func() { itDeploymentShouldBeAvailable(ptr.To(&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "sharder", Namespace: shardingv1alpha1.NamespaceSystem}}), 2) itDeploymentShouldBeAvailable(&controllerDeployment, 3) itControllerRingShouldBeReady() itShouldRecognizeReadyShardLeases(3) It("there should not be any shard leases other than the 3 ready leases", func(ctx SpecContext) { leaseList := &coordinationv1.LeaseList{} Eventually(ctx, ObjectList(leaseList, client.InNamespace(namespace.Name), client.MatchingLabels{shardingv1alpha1.LabelControllerRing: controllerRing.Name}, )).Should(HaveNames(shards...)) }, SpecTimeout(ShortTimeout)) It("should create the MutatingWebhookConfiguration", func(ctx SpecContext) { webhookConfig := &admissionregistrationv1.MutatingWebhookConfiguration{ ObjectMeta: metav1.ObjectMeta{Name: "controllerring-" + controllerRing.Name}, } Eventually(ctx, Object(webhookConfig)).Should(And( HaveLabelWithValue(shardingv1alpha1.LabelControllerRing, controllerRing.Name), HaveField("Webhooks", ConsistOf(And( HaveField("NamespaceSelector", Equal(&metav1.LabelSelector{ MatchLabels: map[string]string{corev1.LabelMetadataName: namespace.Name}, })), HaveField("ObjectSelector", Equal(&metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{{ Key: controllerRing.LabelShard(), Operator: metav1.LabelSelectorOpDoesNotExist, }}, })), HaveField("Rules", ConsistOf( HaveField("Resources", ConsistOf("secrets")), HaveField("Resources", ConsistOf("configmaps")), )), ))), )) }, SpecTimeout(ShortTimeout)) }) Describe("creating a secret", Ordered, func() { var ( secret *corev1.Secret shard string ) itControllerRingShouldBeReady() itShouldRecognizeReadyShardLeases(3) It("should assign the main object to a healthy shard", func(ctx SpecContext) { // Verify that the sharder successfully injects the shard label. // The webhook has failurePolicy=Ignore, so we might need to retry the creation until the injection succeeds. Eventually(ctx, func(g Gomega) *corev1.Secret { secret = newSecret("foo-" + test.RandomSuffix()) g.Expect(testClient.Create(ctx, secret)).To(Succeed()) return secret }).Should(And( HaveLabelWithValue(controllerRing.LabelShard(), BeElementOf(shards)), Not(HaveLabel(controllerRing.LabelDrain())), )) shard = secret.Labels[controllerRing.LabelShard()] log.Info("Created object", "secret", client.ObjectKeyFromObject(secret), "shard", shard) }, SpecTimeout(MediumTimeout)) It("should assign the controlled ConfigMap to the same shard", func(ctx SpecContext) { configMap := &corev1.ConfigMap{} configMap.Name = namePrefixChecksums + secret.Name configMap.Namespace = secret.Namespace Eventually(ctx, Object(configMap)).Should(And( HaveLabelWithValue(controllerRing.LabelShard(), Equal(shard)), Not(HaveLabel(controllerRing.LabelDrain())), )) }, SpecTimeout(MediumTimeout)) }) Describe("creating many secrets", Ordered, func() { itControllerRingShouldBeReady() itShouldRecognizeReadyShardLeases(3) itCreateSecrets() It("should correctly map controlled objects", func(ctx SpecContext) { var usedShards sets.Set[string] Eventually(ctx, func(g Gomega) { secretsList := &corev1.SecretList{} g.Expect(ObjectList(secretsList, client.InNamespace(namespace.Name), client.MatchingLabels(testRunLabels))()).To(HaveField("Items", HaveLen(objectCount))) configMapList := &corev1.ConfigMapList{} g.Expect(ObjectList(configMapList, client.InNamespace(namespace.Name), client.MatchingLabels(testRunLabels))()).To(HaveField("Items", HaveLen(objectCount))) configMaps := toMapOfConfigMap(configMapList.Items) usedShards = sets.New[string]() for _, secret := range secretsList.Items { g.Expect(secret).To(HaveLabelWithValue(controllerRing.LabelShard(), BeElementOf(shards))) g.Expect(secret).NotTo(HaveLabel(controllerRing.LabelDrain())) configMap := configMaps[namePrefixChecksums+secret.Name] g.Expect(configMap).NotTo(BeNil(), "there should be a checksum ConfigMap for Secret %s", secret.Name) g.Expect(configMap).NotTo(HaveLabel(controllerRing.LabelDrain())) g.Expect(configMap.Labels[controllerRing.LabelShard()]).To(Equal(secret.Labels[controllerRing.LabelShard()]), "ConfigMap %s should be assigned to the same shard as the owning Secret", configMap.Name) usedShards.Insert(secret.Labels[controllerRing.LabelShard()]) } }).Should(Succeed(), "ConfigMaps should be assigned to the same shard as the owning Secrets") Expect(usedShards.UnsortedList()).To(ConsistOf(shards), "should use all available shards") }, SpecTimeout(MediumTimeout)) }) describeScaleController("adding a shard", 4) describeScaleController("removing a shard", 2) Describe("graceful shard termination", Ordered, func() { var lease *coordinationv1.Lease BeforeAll(func() { lease = newLease(60) }) itControllerRingShouldBeReady() itCreateShardLease(&lease) itShouldReportShardLeaseState(&lease, leases.Ready) itControllerRingShouldHaveAvailableShards(4) It("release the shard lease", func(ctx SpecContext) { patch := client.MergeFrom(lease.DeepCopy()) lease.Spec.HolderIdentity = nil Expect(testClient.Patch(ctx, lease, patch)).To(Succeed()) }, SpecTimeout(ShortTimeout)) itShouldReportShardLeaseState(&lease, leases.Dead) itControllerRingShouldHaveAvailableShards(3) }) Describe("shard failure detection", Ordered, func() { var lease *coordinationv1.Lease BeforeAll(func() { lease = newLease(10) }) itControllerRingShouldBeReady() itCreateShardLease(&lease) itShouldReportShardLeaseState(&lease, leases.Ready) itControllerRingShouldHaveAvailableShards(4) It("should transition the shard lease to state expired", func(ctx SpecContext) { Eventually(ctx, Object(lease)).Should( HaveLabelWithValue(shardingv1alpha1.LabelState, leases.Expired.String()), ) }, SpecTimeout(15*time.Second)) It("should acquire the shard lease", func(ctx SpecContext) { Eventually(ctx, Object(lease)).Should(And( HaveField("Spec.HolderIdentity", HaveValue(Equal(shardingv1alpha1.IdentityShardLeaseController))), HaveLabelWithValue(shardingv1alpha1.LabelState, leases.Dead.String()), ), "lease should be acquired by sharder") }, SpecTimeout(15*time.Second)) itControllerRingShouldHaveAvailableShards(3) }) }) func describeScaleController(text string, replicas int32) { Describe(text, Ordered, func() { itControllerRingShouldHaveAvailableShards(3) itShouldRecognizeReadyShardLeases(3) itCreateSecrets() itShouldAssignObjectsToAvailableShards() itScaleController(replicas) itDeploymentShouldBeAvailable(&controllerDeployment, replicas) itControllerRingShouldHaveAvailableShards(replicas) itShouldRecognizeReadyShardLeases(int(replicas)) itShouldAssignObjectsToAvailableShards() }) } func newSecret(name string) *corev1.Secret { return &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace.Name, Labels: maps.Clone(testRunLabels), }, } } func itDeploymentShouldBeAvailable(deployment **appsv1.Deployment, expectedReplicas int32) { GinkgoHelper() name := "controller" if *deployment != nil { name = (*deployment).Name } It(fmt.Sprintf("the %s Deployment should be available", name), func(ctx SpecContext) { Eventually(ctx, Object(*deployment)).Should(And( HaveField("Spec.Replicas", HaveValue(BeEquivalentTo(expectedReplicas))), HaveField("Status.Replicas", BeEquivalentTo(expectedReplicas)), HaveField("Status.AvailableReplicas", BeEquivalentTo(expectedReplicas)), )) }, SpecTimeout(ShortTimeout)) } func itControllerRingShouldBeReady() { GinkgoHelper() It("the ControllerRing should be ready", func(ctx SpecContext) { Eventually(ctx, Object(controllerRing)).Should(And( HaveField("Status.Shards", BeEquivalentTo(3)), HaveField("Status.AvailableShards", BeEquivalentTo(3)), HaveField("Status.Conditions", ConsistOf( MatchCondition( OfType(shardingv1alpha1.ControllerRingReady), WithStatus(metav1.ConditionTrue), ), )), )) }, SpecTimeout(ShortTimeout)) } func itControllerRingShouldHaveAvailableShards(expectedAvailableShards int32) { GinkgoHelper() It(fmt.Sprintf("the ControllerRing should be ready and should have %d available shards", expectedAvailableShards), func(ctx SpecContext) { Eventually(ctx, Object(controllerRing)).Should(And( HaveField("Status.AvailableShards", BeEquivalentTo(expectedAvailableShards)), HaveField("Status.Conditions", ConsistOf( MatchCondition( OfType(shardingv1alpha1.ControllerRingReady), WithStatus(metav1.ConditionTrue), ), )), )) }, SpecTimeout(ShortTimeout)) } var shards []string func itShouldRecognizeReadyShardLeases(expectedCount int) { GinkgoHelper() It(fmt.Sprintf("should recognize %d ready shard leases", expectedCount), func(ctx SpecContext) { leaseList := &coordinationv1.LeaseList{} Eventually(ctx, ObjectList(leaseList, client.InNamespace(namespace.Name), client.MatchingLabels{ shardingv1alpha1.LabelControllerRing: controllerRing.Name, shardingv1alpha1.LabelState: leases.Ready.String(), })).Should(HaveField("Items", HaveLen(expectedCount))) shards = make([]string, len(leaseList.Items)) for i, lease := range leaseList.Items { shards[i] = lease.Name } }, SpecTimeout(ShortTimeout)) } func itCreateShardLease(lease **coordinationv1.Lease) { GinkgoHelper() It("create a new shard lease", func(ctx SpecContext) { microNow := metav1.NewMicroTime(time.Now()) (*lease).Spec.AcquireTime = ptr.To(microNow) (*lease).Spec.RenewTime = ptr.To(microNow) Expect(testClient.Create(ctx, *lease)).To(Succeed()) }, SpecTimeout(ShortTimeout)) } func itShouldReportShardLeaseState(lease **coordinationv1.Lease, state leases.ShardState) { GinkgoHelper() It("should mark the shard lease as "+state.String(), func(ctx SpecContext) { Eventually(ctx, Object(*lease)).Should( HaveLabelWithValue(shardingv1alpha1.LabelState, state.String()), ) }, SpecTimeout(ShortTimeout)) } func itCreateSecrets() { GinkgoHelper() It(fmt.Sprintf("create %d secrets", objectCount), func(ctx SpecContext) { for i := 0; i < objectCount; i++ { secret := newSecret("foo-" + strconv.Itoa(i)) Expect(testClient.Create(ctx, secret)).To(Succeed(), "should create secret %s", secret.Name) } }, SpecTimeout(MediumTimeout)) } func itScaleController(replicas int32) { GinkgoHelper() It(fmt.Sprintf("scale the controller to %d replicas", replicas), func(ctx SpecContext) { scaleController(ctx, replicas) }, NodeTimeout(ShortTimeout)) } func scaleController(ctx context.Context, replicas int32) { GinkgoHelper() patch := client.MergeFrom(&autoscalingv1.Scale{}) scale := &autoscalingv1.Scale{Spec: autoscalingv1.ScaleSpec{Replicas: replicas}} Expect(testClient.SubResource("scale").Patch(ctx, controllerDeployment, patch, client.WithSubResourceBody(scale), &client.SubResourcePatchOptions{})).To(Succeed()) log.Info("Scaled controller", "replicas", replicas) } func itShouldAssignObjectsToAvailableShards() { GinkgoHelper() It("should assign the Secrets to the available shards", func(ctx SpecContext) { eventuallyShouldAssignObjectsToAvailableShards(ctx, &corev1.SecretList{}) }, NodeTimeout(MediumTimeout)) It("should assign the controlled ConfigMaps to the available shards", func(ctx SpecContext) { eventuallyShouldAssignObjectsToAvailableShards(ctx, &corev1.ConfigMapList{}) }, NodeTimeout(MediumTimeout)) } func eventuallyShouldAssignObjectsToAvailableShards(ctx context.Context, list client.ObjectList) { GinkgoHelper() Eventually(ctx, func(g Gomega) { g.Expect(ObjectList(list, client.InNamespace(namespace.Name), client.MatchingLabels(testRunLabels))()).To(HaveField("Items", HaveLen(objectCount))) usedShards := sets.New[string]() Expect(meta.EachListItem(list, func(obj runtime.Object) error { g.Expect(obj).To(HaveLabelWithValue(controllerRing.LabelShard(), Not(BeEmpty())), "object %T %s should be assigned") g.Expect(obj).NotTo(HaveLabel(controllerRing.LabelDrain()), "object %T %s should not have drain label") usedShards.Insert(obj.(client.Object).GetLabels()[controllerRing.LabelShard()]) return nil })).To(Succeed()) g.Expect(usedShards.UnsortedList()).To(ConsistOf(shards), "should use all available shards") }).Should(Succeed()) } func newLease(leaseDurationSeconds int32) *coordinationv1.Lease { name := "test-" + test.RandomSuffix() return &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace.Name, Labels: map[string]string{ shardingv1alpha1.LabelControllerRing: controllerRing.Name, }, }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To(name), LeaseDurationSeconds: ptr.To[int32](leaseDurationSeconds), }, } } func toMapOfConfigMap(configMaps []corev1.ConfigMap) map[string]*corev1.ConfigMap { out := make(map[string]*corev1.ConfigMap, len(configMaps)) for _, configMap := range configMaps { out[configMap.Name] = &configMap } return out } ================================================ FILE: test/e2e/e2e_suite_test.go ================================================ /* Copyright 2024 Tim Ebert. 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. */ package e2e import ( "context" "fmt" "maps" "testing" "time" "github.com/go-logr/logr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/envtest/komega" "sigs.k8s.io/controller-runtime/pkg/log/zap" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) func TestE2E(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Controller Sharding E2E Test Suite") } const ( testID = "e2e-controller-sharding" ShortTimeout = 10 * time.Second MediumTimeout = time.Minute ) var ( log logr.Logger testClient client.Client testRunID string testRunLabels map[string]string ) var _ = BeforeSuite(func() { log = zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter)).WithName(testID) restConfig, err := config.GetConfig() Expect(err).NotTo(HaveOccurred()) scheme := runtime.NewScheme() schemeBuilder := runtime.NewSchemeBuilder( clientgoscheme.AddToScheme, shardingv1alpha1.AddToScheme, ) Expect(schemeBuilder.AddToScheme(scheme)).To(Succeed()) testClient, err = client.New(restConfig, client.Options{Scheme: scheme}) Expect(err).NotTo(HaveOccurred()) clientContext, clientCancel := context.WithCancel(context.Background()) komega.SetClient(testClient) komega.SetContext(clientContext) DeferCleanup(clientCancel) testRunID = testID + "-" + test.RandomSuffix() testRunLabels = map[string]string{ testID: testRunID, } log = log.WithValues("testRun", testRunID) }) var ( controllerRing *shardingv1alpha1.ControllerRing namespace *corev1.Namespace controllerDeployment *appsv1.Deployment ) var _ = BeforeEach(func(ctx SpecContext) { By("Set up test Namespace") namespace = &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{ GenerateName: testRunID + "-", Labels: maps.Clone(testRunLabels), }} // We create a dedicated test namespace and clean it up for every test case to ensure a clean test environment. Expect(testClient.Create(ctx, namespace)).To(Succeed()) log.Info("Created test Namespace", "namespace", namespace.Name) DeferCleanup(func(ctx SpecContext) { By("Delete test Namespace") Eventually(ctx, func() error { return testClient.Delete(ctx, namespace) }).Should(Or(Succeed(), BeNotFoundError())) }, NodeTimeout(MediumTimeout)) By("Set up test ControllerRing") // Deploy a dedicated ControllerRing instance for this test case defaultControllerRing := &shardingv1alpha1.ControllerRing{ObjectMeta: metav1.ObjectMeta{Name: checksumControllerName}} Expect(komega.Get(defaultControllerRing)()).To(Succeed()) controllerRing = defaultControllerRing.DeepCopy() controllerRing.Name = namespace.Name controllerRing.ResourceVersion = "" maps.Copy(controllerRing.Labels, testRunLabels) controllerRing.Spec.NamespaceSelector.MatchLabels[corev1.LabelMetadataName] = namespace.Name Expect(testClient.Create(ctx, controllerRing)).To(Succeed()) DeferCleanup(func(ctx SpecContext) { By("Delete test ControllerRing") Eventually(ctx, func() error { return testClient.Delete(ctx, controllerRing) }).Should(Or(Succeed(), BeNotFoundError())) }, NodeTimeout(ShortTimeout)) By("Set up test controller") controllerDeployment = &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Namespace: namespace.Name, Name: checksumControllerName}} // Deploy a dedicated controller instance to this test case's namespace. // Copy all relevant objects from the default namespace. for _, objList := range []client.ObjectList{ &appsv1.DeploymentList{}, &corev1.ServiceAccountList{}, &rbacv1.RoleList{}, &rbacv1.RoleBindingList{}, } { Expect(testClient.List(ctx, objList, client.InNamespace(metav1.NamespaceDefault), client.MatchingLabels{"app.kubernetes.io/component": checksumControllerName})). Should(Succeed(), "should list %T in default namespace", objList) Expect(meta.EachListItem(objList, func(object runtime.Object) error { obj := object.DeepCopyObject().(client.Object) obj.SetNamespace(namespace.Name) obj.SetResourceVersion("") switch o := obj.(type) { case *appsv1.Deployment: o.Spec.Replicas = ptr.To[int32](3) o.Spec.Template.Spec.Containers[0].Args = append(o.Spec.Template.Spec.Containers[0].Args, "--controllerring="+controllerRing.Name, "--namespace="+namespace.Name, ) case *rbacv1.RoleBinding: o.Subjects[0].Namespace = namespace.Name } if err := testClient.Create(ctx, obj); err != nil { return fmt.Errorf("error copying object %T %q to %s namespace: %w", obj, client.ObjectKeyFromObject(obj), namespace.Name, err) } return nil })).To(Succeed(), "should copy %T", objList) } }, NodeTimeout(MediumTimeout), OncePerOrdered) ================================================ FILE: test/integration/shard/controller/controller_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controller_test import ( "context" "testing" "time" "github.com/go-logr/logr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" "sigs.k8s.io/controller-runtime/pkg/envtest/komega" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" . "github.com/timebertt/kubernetes-controller-sharding/test/integration/shard/controller" ) func TestController(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Shard Controller Integration Test Suite") } const testID = "shard-controller-test" var ( log logr.Logger testClient client.Client controllerRingName, shardName string shardLabel, drainLabel string testRunID string ) var _ = BeforeSuite(func(ctx SpecContext) { logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter))) log = logf.Log.WithName(testID) By("Start test environment") testEnv := &envtest.Environment{} restConfig, err := testEnv.Start() Expect(err).NotTo(HaveOccurred()) Expect(restConfig).NotTo(BeNil()) DeferCleanup(func() { By("Stop test environment") Expect(testEnv.Stop()).To(Succeed()) }) By("Create test clients") testClient, err = client.New(restConfig, client.Options{}) Expect(err).NotTo(HaveOccurred()) Expect(testClient).NotTo(BeNil()) clientContext, clientCancel := context.WithCancel(context.Background()) komega.SetClient(testClient) komega.SetContext(clientContext) DeferCleanup(clientCancel) By("Create test Namespace") testNamespace := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ GenerateName: testID + "-", }, } Expect(testClient.Create(ctx, testNamespace)).To(Succeed()) log.Info("Created Namespace for test", "namespaceName", testNamespace.Name) testRunID = testNamespace.Name log = log.WithValues("testRunID", testRunID) controllerRingName = testRunID shardName = testRunID shardLabel = "shard.alpha.sharding.timebertt.dev/" + controllerRingName drainLabel = "drain.alpha.sharding.timebertt.dev/" + controllerRingName DeferCleanup(func(ctx SpecContext) { By("Delete test Namespace") Expect(testClient.Delete(ctx, testNamespace)).To(Or(Succeed(), BeNotFoundError())) }, NodeTimeout(time.Minute)) By("Setup manager") mgr, err := manager.New(restConfig, manager.Options{ Metrics: metricsserver.Options{BindAddress: "0"}, Cache: cache.Options{ DefaultNamespaces: map[string]cache.Config{testNamespace.Name: {}}, }, }) Expect(err).NotTo(HaveOccurred()) By("Register controller") Expect((&Reconciler{}).AddToManager(mgr, controllerRingName, shardName)).To(Succeed()) By("Start manager") mgrContext, mgrCancel := context.WithCancel(context.Background()) go func() { defer GinkgoRecover() Expect(mgr.Start(mgrContext)).To(Succeed()) }() DeferCleanup(func() { By("Stop manager") mgrCancel() }) }, NodeTimeout(time.Minute)) ================================================ FILE: test/integration/shard/controller/controller_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controller_test import ( "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" gomegatypes "github.com/onsi/gomega/types" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" . "sigs.k8s.io/controller-runtime/pkg/envtest/komega" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" . "github.com/timebertt/kubernetes-controller-sharding/test/integration/shard/controller" ) var obj *corev1.ConfigMap var _ = Describe("Shard controller", func() { BeforeEach(func() { obj = &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "test-", Namespace: testRunID, Labels: map[string]string{ shardLabel: shardName, LabelKey: LabelValuePending, }, }, } }, OncePerOrdered) JustBeforeEach(func(ctx SpecContext) { Expect(testClient.Create(ctx, obj)).To(Succeed()) log.Info("Created ConfigMap for test", "configMapName", obj.Name) }, NodeTimeout(time.Minute), OncePerOrdered) When("the object is assigned on Create event", func() { itShouldReconcile() itShouldDrain() When("the predicate does not match the object", func() { BeforeEach(ignoreObject, OncePerOrdered) itShouldNotReconcile() itShouldDrain() }) When("the object should be drained on Create event", Ordered, func() { BeforeAll(drainObject) itShouldRemoveShardingLabels() itShouldNotReconcile() }) }) When("the object is assigned to a different shard on Create event", func() { BeforeEach(assignOtherShard, OncePerOrdered) itShouldNotReconcile() itShouldNotDrain() When("the object gets assigned", Ordered, func() { itShouldNotReconcile() It("assign object", func(ctx SpecContext) { Eventually(ctx, Update(obj, assignThisShard)).Should(Succeed()) }, SpecTimeout(time.Minute)) itShouldReconcile() }) }) }) func itShouldReconcile() { GinkgoHelper() It("should reconcile the object", func(ctx SpecContext) { Eventually(ctx, Object(obj)).Should(haveStatus(LabelValueDone)) }, SpecTimeout(time.Minute)) } func itShouldNotReconcile() { GinkgoHelper() It("should not reconcile the object", func(ctx SpecContext) { Consistently(ctx, Object(obj)).Should(haveStatus(obj.Labels[LabelKey])) }, SpecTimeout(time.Minute)) } func itShouldDrain() { GinkgoHelper() Describe("should handle the drain operation", Ordered, func() { itAddDrainLabel() itShouldRemoveShardingLabels() itShouldNotReconcile() }) } func itShouldNotDrain() { GinkgoHelper() Context("should not handle drain operation", Ordered, func() { itAddDrainLabel() It("should not remove shard and drain labels", func(ctx SpecContext) { Consistently(ctx, Object(obj)).Should(And( HaveLabel(shardLabel), HaveLabel(drainLabel), )) }, SpecTimeout(time.Minute)) }) } func itAddDrainLabel() { GinkgoHelper() It("add the drain label", func(ctx SpecContext) { Eventually(ctx, Update(obj, drainObject)).Should(Succeed()) }, SpecTimeout(time.Minute)) } func itShouldRemoveShardingLabels() { GinkgoHelper() It("should remove shard and drain labels", func(ctx SpecContext) { Eventually(ctx, Object(obj)).Should(And( Not(HaveLabel(shardLabel)), Not(HaveLabel(drainLabel)), )) }, SpecTimeout(time.Minute)) } func haveStatus(status string) gomegatypes.GomegaMatcher { return HaveLabelWithValue(LabelKey, status) } func ignoreObject() { obj.Labels[LabelKey] = LabelValueIgnore } func assignThisShard() { obj.Labels[shardLabel] = shardName } func assignOtherShard() { obj.Labels[shardLabel] = "other" } func drainObject() { obj.Labels[drainLabel] = "true" } ================================================ FILE: test/integration/shard/controller/reconciler.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controller import ( "context" "fmt" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" shardcontroller "github.com/timebertt/kubernetes-controller-sharding/pkg/shard/controller" ) const ( LabelKey = "status" LabelValuePending = "pending" LabelValueDone = "done" LabelValueIgnore = "ignore" ) // Reconciler watches ConfigMaps with the `status=pending` label and sets the `status` label to `done`. type Reconciler struct { Client client.Client } // AddToManager adds Reconciler to the given manager. func (r *Reconciler) AddToManager(mgr manager.Manager, controllerRingName, shardName string) error { if r.Client == nil { r.Client = mgr.GetClient() } return builder.ControllerManagedBy(mgr). Named("test"). For(&corev1.ConfigMap{}, builder.WithPredicates(shardcontroller.Predicate(controllerRingName, shardName, ConfigMapPredicate()))). WithOptions(controller.Options{ MaxConcurrentReconciles: 5, }). Complete( shardcontroller.NewShardedReconciler(mgr). For(&corev1.ConfigMap{}). InControllerRing(controllerRingName). WithShardName(shardName). MustBuild(r), ) } func ConfigMapPredicate() predicate.Predicate { return predicate.NewPredicateFuncs(func(obj client.Object) bool { return obj.GetLabels()[LabelKey] == LabelValuePending }) } // Reconcile reconciles a ConfigMap. func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) { log := logf.FromContext(ctx) secret := &corev1.ConfigMap{} if err := r.Client.Get(ctx, req.NamespacedName, secret); err != nil { if apierrors.IsNotFound(err) { log.V(1).Info("Object is gone, stop reconciling") return reconcile.Result{}, nil } return reconcile.Result{}, fmt.Errorf("error retrieving object from store: %w", err) } log.V(1).Info("Reconciling object") patch := client.MergeFrom(secret.DeepCopy()) metav1.SetMetaDataLabel(&secret.ObjectMeta, LabelKey, LabelValueDone) return reconcile.Result{}, r.Client.Patch(ctx, secret, patch) } ================================================ FILE: test/integration/shard/lease/lease_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controller_test import ( "context" "testing" "time" "github.com/go-logr/logr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" "sigs.k8s.io/controller-runtime/pkg/envtest/komega" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) func TestController(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Shard Lease Integration Test Suite") } const testID = "shard-lease-test" var ( log logr.Logger restConfig *rest.Config testClient client.Client testRunID string ) var _ = BeforeSuite(func(ctx SpecContext) { logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter))) log = logf.Log.WithName(testID) By("Start test environment") testEnv := &envtest.Environment{} var err error restConfig, err = testEnv.Start() Expect(err).NotTo(HaveOccurred()) Expect(restConfig).NotTo(BeNil()) DeferCleanup(func() { By("Stop test environment") Expect(testEnv.Stop()).To(Succeed()) }) By("Create test clients") testClient, err = client.New(restConfig, client.Options{}) Expect(err).NotTo(HaveOccurred()) Expect(testClient).NotTo(BeNil()) clientContext, clientCancel := context.WithCancel(context.Background()) komega.SetClient(testClient) komega.SetContext(clientContext) DeferCleanup(clientCancel) By("Create test Namespace") testNamespace := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ GenerateName: testID + "-", }, } Expect(testClient.Create(ctx, testNamespace)).To(Succeed()) log.Info("Created Namespace for test", "namespaceName", testNamespace.Name) testRunID = testNamespace.Name log = log.WithValues("testRunID", testRunID) DeferCleanup(func(ctx SpecContext) { By("Delete test Namespace") Expect(testClient.Delete(ctx, testNamespace)).To(Or(Succeed(), BeNotFoundError())) }, NodeTimeout(time.Minute)) }, NodeTimeout(time.Minute)) ================================================ FILE: test/integration/shard/lease/lease_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controller_test import ( "context" "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" . "sigs.k8s.io/controller-runtime/pkg/envtest/komega" "sigs.k8s.io/controller-runtime/pkg/manager" shardlease "github.com/timebertt/kubernetes-controller-sharding/pkg/shard/lease" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" ) var _ = Describe("Shard lease", func() { var ( mgrOptions manager.Options mgrCancel context.CancelFunc leaseOptions shardlease.Options lease *coordinationv1.Lease ) BeforeEach(func() { mgrOptions = manager.Options{ LeaderElection: true, LeaderElectionResourceLock: "should-be-ignored", // -> should use provided lock instead LeaderElectionNamespace: "should-be-ignored", // -> should use provided namespace in lock instead LeaderElectionID: "should-be-ignored", // -> should be shard name instead LeaseDuration: ptr.To(time.Second), RenewDeadline: ptr.To(100 * time.Millisecond), RetryPeriod: ptr.To(50 * time.Millisecond), } leaseOptions = shardlease.Options{ ControllerRingName: "test-" + test.RandomSuffix(), LeaseNamespace: testRunID, ShardName: "test-" + test.RandomSuffix(), } lease = &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Namespace: leaseOptions.LeaseNamespace, Name: leaseOptions.ShardName, }, } }, OncePerOrdered) JustBeforeEach(func() { shardLease, err := shardlease.NewResourceLock(restConfig, leaseOptions) Expect(err).NotTo(HaveOccurred()) mgrOptions.LeaderElectionResourceLockInterface = shardLease By("Setup manager") mgrOptions.Metrics.BindAddress = "0" mgr, err := manager.New(restConfig, mgrOptions) Expect(err).NotTo(HaveOccurred()) By("Start manager") var mgrContext context.Context mgrContext, mgrCancel = context.WithCancel(context.Background()) mgrDone := make(chan struct{}) go func() { defer GinkgoRecover() Expect(mgr.Start(mgrContext)).To(Succeed()) close(mgrDone) }() DeferCleanup(func(ctx SpecContext) { By("Stop manager") mgrCancel() By("Wait for manager to stop") Eventually(ctx, mgrDone).Should(BeClosed()) }, NodeTimeout(time.Minute)) }, OncePerOrdered) Describe("should maintain the shard lease", Ordered, func() { It("should create the shard lease according to the config", func(ctx SpecContext) { Eventually(ctx, Object(lease)).Should(And( HaveField("ObjectMeta.Labels", HaveKeyWithValue("alpha.sharding.timebertt.dev/controllerring", leaseOptions.ControllerRingName)), HaveField("Spec.HolderIdentity", HaveValue(Equal(leaseOptions.ShardName))), HaveField("Spec.LeaseDurationSeconds", HaveValue(BeEquivalentTo(1))), HaveField("Spec.AcquireTime", Not(BeNil())), HaveField("Spec.RenewTime", Not(BeNil())), )) }, SpecTimeout(time.Minute)) It("should renew the shard lease", func(ctx SpecContext) { Eventually(ctx, Object(lease)).Should(And( HaveField("Spec.HolderIdentity", HaveValue(Equal(leaseOptions.ShardName))), HaveField("Spec.LeaseDurationSeconds", HaveValue(BeEquivalentTo(1))), HaveField("Spec.AcquireTime.Time", BeTemporally("~", lease.Spec.AcquireTime.Time)), HaveField("Spec.RenewTime.Time", BeTemporally(">", lease.Spec.RenewTime.Time)), )) }, SpecTimeout(time.Minute)) }) Describe("should renew shard lease that was acquired by sharder", Ordered, func() { var sharderAcquireTime time.Time BeforeAll(func(ctx SpecContext) { sharderAcquireTime = time.Now() lease.Spec.HolderIdentity = ptr.To("sharder") lease.Spec.AcquireTime = ptr.To(metav1.NewMicroTime(sharderAcquireTime)) lease.Spec.RenewTime = ptr.To(metav1.NewMicroTime(sharderAcquireTime)) lease.Spec.LeaseDurationSeconds = ptr.To[int32](3) lease.Spec.LeaseTransitions = ptr.To[int32](1) Eventually(ctx, func() error { return testClient.Create(ctx, lease) }).Should(Succeed()) }, NodeTimeout(time.Minute)) It("should wait for lease to expire", func(ctx SpecContext) { Consistently(ctx, Object(lease)).WithTimeout(2 * time.Second).ShouldNot( HaveField("Spec.HolderIdentity", HaveValue(Equal(leaseOptions.ShardName))), ) }, SpecTimeout(time.Minute)) It("should renew the shard lease", func(ctx SpecContext) { Eventually(ctx, Object(lease)).Should(And( HaveField("Spec.HolderIdentity", HaveValue(Equal(leaseOptions.ShardName))), HaveField("Spec.LeaseDurationSeconds", HaveValue(BeEquivalentTo(1))), HaveField("Spec.AcquireTime.Time", BeTemporally(">", sharderAcquireTime)), HaveField("Spec.RenewTime.Time", BeTemporally(">", sharderAcquireTime)), HaveField("Spec.LeaseTransitions", HaveValue(BeEquivalentTo(2))), )) }, SpecTimeout(time.Minute)) }) When("LeaderElectionReleaseOnCancel is true", Ordered, func() { BeforeAll(func() { mgrOptions.LeaderElectionReleaseOnCancel = true }) It("should create the shard lease", func(ctx SpecContext) { Eventually(ctx, Object(lease)).Should( HaveField("Spec.HolderIdentity", HaveValue(Equal(leaseOptions.ShardName))), ) }, SpecTimeout(time.Minute)) It("should release the shard lease when canceling the manager", func(ctx SpecContext) { mgrCancel() Eventually(ctx, Object(lease)).Should( HaveField("Spec.HolderIdentity", HaveValue(BeEmpty())), ) }, SpecTimeout(time.Minute)) }) }) ================================================ FILE: test/integration/sharder/controller/controllerring/controllerring_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controllerring_test import ( "context" "testing" "time" "github.com/go-logr/logr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" testclock "k8s.io/utils/clock/testing" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" "sigs.k8s.io/controller-runtime/pkg/envtest/komega" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" configv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/config/v1alpha1" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/controller/controllerring" utilclient "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/client" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) func TestControllerRing(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Sharder ControllerRing Controller Integration Test Suite") } const testID = "controllerring-controller-test" var ( log logr.Logger testClient client.Client clock *testclock.FakePassiveClock testRunID string testRunLabels map[string]string ) var _ = BeforeSuite(func(ctx SpecContext) { logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter))) log = logf.Log.WithName(testID) By("Start test environment") testEnv := &envtest.Environment{ CRDInstallOptions: envtest.CRDInstallOptions{ Paths: []string{test.PathShardingCRDs()}, }, ErrorIfCRDPathMissing: true, } restConfig, err := testEnv.Start() Expect(err).NotTo(HaveOccurred()) Expect(restConfig).NotTo(BeNil()) DeferCleanup(func() { By("Stop test environment") Expect(testEnv.Stop()).To(Succeed()) }) By("Create test clients") testClient, err = client.New(restConfig, client.Options{Scheme: utilclient.SharderScheme}) Expect(err).NotTo(HaveOccurred()) Expect(testClient).NotTo(BeNil()) clientContext, clientCancel := context.WithCancel(context.Background()) komega.SetClient(testClient) komega.SetContext(clientContext) DeferCleanup(clientCancel) By("Create test Namespace") testNamespace := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ GenerateName: testID + "-", }, } Expect(testClient.Create(ctx, testNamespace)).To(Succeed()) log.Info("Created Namespace for test", "namespaceName", testNamespace.Name) testRunID = testNamespace.Name log = log.WithValues("testRunID", testRunID) testRunLabels = map[string]string{testID: testRunID} DeferCleanup(func(ctx SpecContext) { By("Delete test Namespace") Expect(testClient.Delete(ctx, testNamespace)).To(Or(Succeed(), BeNotFoundError())) }, NodeTimeout(time.Minute)) By("Setup manager") mgr, err := manager.New(restConfig, manager.Options{ Scheme: utilclient.SharderScheme, Metrics: metricsserver.Options{BindAddress: "0"}, Cache: cache.Options{ DefaultNamespaces: map[string]cache.Config{testNamespace.Name: {}}, ByObject: map[client.Object]cache.ByObject{ &shardingv1alpha1.ControllerRing{}: { Label: labels.SelectorFromSet(testRunLabels), }, }, }, }) Expect(err).NotTo(HaveOccurred()) By("Register controller") config := &configv1alpha1.SharderConfig{} mgr.GetScheme().Default(config) clock = testclock.NewFakePassiveClock(time.Now()) Expect((&controllerring.Reconciler{ Clock: clock, Config: config, }).AddToManager(mgr)).To(Succeed()) By("Start manager") mgrContext, mgrCancel := context.WithCancel(context.Background()) go func() { defer GinkgoRecover() Expect(mgr.Start(mgrContext)).To(Succeed()) }() DeferCleanup(func() { By("Stop manager") mgrCancel() }) }, NodeTimeout(time.Minute)) ================================================ FILE: test/integration/sharder/controller/controllerring/controllerring_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package controllerring_test import ( "maps" "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" gomegatypes "github.com/onsi/gomega/types" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" . "sigs.k8s.io/controller-runtime/pkg/envtest/komega" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) var _ = Describe("ControllerRing controller", func() { var ( controllerRing *shardingv1alpha1.ControllerRing ) BeforeEach(func(ctx SpecContext) { controllerRing = &shardingv1alpha1.ControllerRing{ ObjectMeta: metav1.ObjectMeta{ GenerateName: testRunID + "-", Labels: maps.Clone(testRunLabels), }, Spec: shardingv1alpha1.ControllerRingSpec{ Resources: []shardingv1alpha1.RingResource{ { GroupResource: metav1.GroupResource{Group: "apps", Resource: "deployments"}, }, }, }, } Expect(testClient.Create(ctx, controllerRing)).To(Succeed()) log.Info("Created ControllerRing for test", "controllerRingName", controllerRing.Name) DeferCleanup(func(ctx SpecContext) { Expect(testClient.Delete(ctx, controllerRing)).To(Or(Succeed(), BeNotFoundError())) }, NodeTimeout(time.Minute)) }, NodeTimeout(time.Minute), OncePerOrdered) It("should observe the generation", func(ctx SpecContext) { Eventually(ctx, Object(controllerRing)).Should( HaveField("Status.ObservedGeneration", Equal(controllerRing.Generation)), ) }, SpecTimeout(time.Minute)) It("should report readiness", func(ctx SpecContext) { Eventually(ctx, Object(controllerRing)).Should( HaveField("Status.Conditions", ConsistOf( MatchCondition( OfType(shardingv1alpha1.ControllerRingReady), WithStatus(metav1.ConditionTrue), ), )), ) }, SpecTimeout(time.Minute)) It("should apply the sharder webhook", func(ctx SpecContext) { webhookConfig := &admissionregistrationv1.MutatingWebhookConfiguration{ ObjectMeta: metav1.ObjectMeta{Name: "controllerring-" + controllerRing.Name}, } Eventually(ctx, Object(webhookConfig)).Should(And( HaveField("ObjectMeta.OwnerReferences", ConsistOf(And( HaveField("Kind", Equal("ControllerRing")), HaveField("Name", Equal(controllerRing.Name)), ))), HaveField("Webhooks", ConsistOf(And( HaveField("ClientConfig.Service.Path", HaveValue(Equal("/webhooks/sharder/controllerring/"+controllerRing.Name))), HaveField("Rules", ConsistOf(And( HaveField("APIGroups", ConsistOf("apps")), HaveField("Resources", ConsistOf("deployments")), ))), ))), )) }, SpecTimeout(time.Minute)) Describe("should reflect the shard leases in the status", Ordered, func() { var lease *coordinationv1.Lease It("create available shard lease", func(ctx SpecContext) { lease = newLease(controllerRing.Name) Expect(testClient.Create(ctx, lease)).To(Succeed()) Eventually(ctx, Object(controllerRing)).Should(haveStatusShards(1, 1)) }, SpecTimeout(time.Minute)) It("create orphaned shard lease", func(ctx SpecContext) { lease = newLease(controllerRing.Name) lease.Spec.HolderIdentity = nil Expect(testClient.Create(ctx, lease)).To(Succeed()) Eventually(ctx, Object(controllerRing)).Should(haveStatusShards(1, 2)) }, SpecTimeout(time.Minute)) It("make lease healthy", func(ctx SpecContext) { Eventually(ctx, Update(lease, func() { lease.Spec.HolderIdentity = ptr.To(lease.Name) })).Should(Succeed()) Eventually(ctx, Object(controllerRing)).Should(haveStatusShards(2, 2)) }, SpecTimeout(time.Minute)) It("make lease unhealthy", func(ctx SpecContext) { Eventually(ctx, Update(lease, func() { lease.Spec.HolderIdentity = nil })).Should(Succeed()) Eventually(ctx, Object(controllerRing)).Should(haveStatusShards(1, 2)) }, SpecTimeout(time.Minute)) It("delete unhealthy lease", func(ctx SpecContext) { Expect(testClient.Delete(ctx, lease)).To(Succeed()) Eventually(ctx, Object(controllerRing)).Should(haveStatusShards(1, 1)) }, SpecTimeout(time.Minute)) }) }) func newLease(controllerRingName string) *coordinationv1.Lease { name := testRunID + "-" + test.RandomSuffix() return &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: testRunID, Labels: map[string]string{ shardingv1alpha1.LabelControllerRing: controllerRingName, }, }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To(name), LeaseDurationSeconds: ptr.To[int32](10), AcquireTime: ptr.To(metav1.NewMicroTime(clock.Now().Add(-5 * time.Minute))), RenewTime: ptr.To(metav1.NewMicroTime(clock.Now().Add(-2 * time.Second))), }, } } func haveStatusShards(availableShards, shards int32) gomegatypes.GomegaMatcher { return And( HaveField("Status.AvailableShards", Equal(availableShards)), HaveField("Status.Shards", Equal(shards)), ) } ================================================ FILE: test/integration/sharder/controller/sharder/sharder_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package sharder_test import ( "context" "maps" "testing" "time" "github.com/go-logr/logr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" testclock "k8s.io/utils/clock/testing" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" "sigs.k8s.io/controller-runtime/pkg/envtest/komega" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" configv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/config/v1alpha1" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/controller/sharder" utilclient "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/client" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) func TestSharder(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Sharder Controller Integration Test Suite") } const testID = "sharder-controller-test" var ( log logr.Logger testClient client.Client mgrClient client.Client clock *testclock.FakePassiveClock testRunID string testRunLabels map[string]string controllerRing *shardingv1alpha1.ControllerRing ) var _ = BeforeSuite(func(ctx SpecContext) { logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter))) log = logf.Log.WithName(testID) By("Start test environment") testEnv := &envtest.Environment{ CRDInstallOptions: envtest.CRDInstallOptions{ Paths: []string{test.PathShardingCRDs()}, }, ErrorIfCRDPathMissing: true, } restConfig, err := testEnv.Start() Expect(err).NotTo(HaveOccurred()) Expect(restConfig).NotTo(BeNil()) DeferCleanup(func() { By("Stop test environment") Expect(testEnv.Stop()).To(Succeed()) }) By("Create test clients") testClient, err = client.New(restConfig, client.Options{Scheme: utilclient.SharderScheme}) Expect(err).NotTo(HaveOccurred()) Expect(testClient).NotTo(BeNil()) clientContext, clientCancel := context.WithCancel(context.Background()) komega.SetClient(testClient) komega.SetContext(clientContext) DeferCleanup(clientCancel) By("Create test Namespace") testNamespace := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ GenerateName: testID + "-", }, } Expect(testClient.Create(ctx, testNamespace)).To(Succeed()) log.Info("Created Namespace for test", "namespaceName", testNamespace.Name) testRunID = testNamespace.Name log = log.WithValues("testRunID", testRunID) testRunLabels = map[string]string{testID: testRunID} DeferCleanup(func(ctx SpecContext) { By("Delete test Namespace") Expect(testClient.Delete(ctx, testNamespace)).To(Or(Succeed(), BeNotFoundError())) }, NodeTimeout(time.Minute)) By("Create test ControllerRing") controllerRing = &shardingv1alpha1.ControllerRing{ ObjectMeta: metav1.ObjectMeta{ Name: testRunID, Labels: maps.Clone(testRunLabels), }, Spec: shardingv1alpha1.ControllerRingSpec{ Resources: []shardingv1alpha1.RingResource{{ GroupResource: metav1.GroupResource{Group: "", Resource: "secrets"}, ControlledResources: []metav1.GroupResource{{Group: "", Resource: "configmaps"}}, }}, NamespaceSelector: &metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{{ Key: corev1.LabelMetadataName, Operator: metav1.LabelSelectorOpIn, Values: []string{testRunID}, }}, }, }, } Expect(testClient.Create(ctx, controllerRing)).To(Succeed()) log.Info("Created ControllerRing for test", "controllerRingName", controllerRing.Name) DeferCleanup(func(ctx SpecContext) { By("Delete test ControllerRing") Expect(testClient.Delete(ctx, controllerRing)).To(Or(Succeed(), BeNotFoundError())) }, NodeTimeout(time.Minute)) By("Setup manager") mgr, err := manager.New(restConfig, manager.Options{ Scheme: utilclient.SharderScheme, Metrics: metricsserver.Options{BindAddress: "0"}, Cache: cache.Options{ DefaultNamespaces: map[string]cache.Config{ testNamespace.Name: {}, metav1.NamespaceDefault: {}, }, ByObject: map[client.Object]cache.ByObject{ &shardingv1alpha1.ControllerRing{}: { Label: labels.SelectorFromSet(testRunLabels), }, }, }, }) Expect(err).NotTo(HaveOccurred()) mgrClient = mgr.GetClient() By("Register controller") config := &configv1alpha1.SharderConfig{} mgr.GetScheme().Default(config) clock = testclock.NewFakePassiveClock(time.Now()) Expect((&sharder.Reconciler{ Clock: clock, Config: config, }).AddToManager(mgr)).To(Succeed()) By("Start manager") mgrContext, mgrCancel := context.WithCancel(context.Background()) go func() { defer GinkgoRecover() Expect(mgr.Start(mgrContext)).To(Succeed()) }() DeferCleanup(func() { By("Stop manager") mgrCancel() }) }, NodeTimeout(time.Minute)) ================================================ FILE: test/integration/sharder/controller/sharder/sharder_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package sharder_test import ( "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" coordinationv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" . "sigs.k8s.io/controller-runtime/pkg/envtest/komega" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/controller/sharder" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/key" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) var _ = Describe("Sharder controller", func() { var ( mainObj *corev1.Secret controlledObj *corev1.ConfigMap availableShard, deadShard *coordinationv1.Lease ) BeforeEach(func(ctx SpecContext) { mainObj = newObject(&corev1.Secret{}) controlledObj = newObject(&corev1.ConfigMap{}) // We only test the controller in this test and not the webhook. Hence, the objects will not actually be assigned // after the controller triggers assignments. To verify that the sharder triggered assignments, we add the drain // label with an otherwise unused value. The sharder always removes the drain label when triggering assignments. // When triggering the drain operation, the sharder sets this label to another value. metav1.SetMetaDataLabel(&mainObj.ObjectMeta, controllerRing.LabelDrain(), "test") metav1.SetMetaDataLabel(&controlledObj.ObjectMeta, controllerRing.LabelDrain(), "test") availableShard = newLease() deadShard = newLease() deadShard.Spec.HolderIdentity = nil Expect(testClient.Create(ctx, deadShard)).To(Succeed()) DeferCleanup(func(ctx SpecContext) { // clean up all leases from this test case Expect(testClient.DeleteAllOf(ctx, &coordinationv1.Lease{}, client.InNamespace(testRunID))).To(Succeed()) // wait until the manager no longer sees leases from this test case Eventually(ctx, New(mgrClient).ObjectList(&coordinationv1.LeaseList{}, client.InNamespace(testRunID))).Should(HaveField("Items", BeEmpty())) }, NodeTimeout(time.Minute)) }, NodeTimeout(time.Minute)) JustBeforeEach(func(ctx SpecContext) { Expect(testClient.Create(ctx, mainObj)).To(Succeed()) Expect(controllerutil.SetControllerReference(mainObj, controlledObj, testClient.Scheme())).To(Succeed()) Expect(testClient.Create(ctx, controlledObj)).To(Succeed()) }, NodeTimeout(time.Minute)) When("the first shard becomes available", func() { JustBeforeEach(func(ctx SpecContext) { Expect(testClient.Create(ctx, availableShard)).To(Succeed()) }, NodeTimeout(time.Minute)) When("objects are not assigned", func() { It("should trigger assignments", func(ctx SpecContext) { Eventually(ctx, Object(mainObj)).Should(Not(HaveLabel(controllerRing.LabelDrain()))) Eventually(ctx, Object(controlledObj)).Should(Not(HaveLabel(controllerRing.LabelDrain()))) }, SpecTimeout(time.Minute)) }) When("objects are assigned to unavailable shard", func() { BeforeEach(func(ctx SpecContext) { metav1.SetMetaDataLabel(&mainObj.ObjectMeta, controllerRing.LabelShard(), deadShard.Name) metav1.SetMetaDataLabel(&controlledObj.ObjectMeta, controllerRing.LabelShard(), deadShard.Name) }, NodeTimeout(time.Minute)) It("should trigger assignments", func(ctx SpecContext) { Eventually(ctx, Object(mainObj)).Should(And( Not(HaveLabel(controllerRing.LabelShard())), Not(HaveLabel(controllerRing.LabelDrain())), )) Eventually(ctx, Object(controlledObj)).Should(And( Not(HaveLabel(controllerRing.LabelShard())), Not(HaveLabel(controllerRing.LabelDrain())), )) }, SpecTimeout(time.Minute)) }) When("objects are not in a selected namespace", func() { BeforeEach(func() { mainObj.Namespace = metav1.NamespaceDefault controlledObj.Namespace = metav1.NamespaceDefault }) It("should not trigger assignments", func(ctx SpecContext) { Consistently(ctx, Object(mainObj)).Should(HaveLabelWithValue(controllerRing.LabelDrain(), "test")) Consistently(ctx, Object(controlledObj)).Should(HaveLabelWithValue(controllerRing.LabelDrain(), "test")) }, SpecTimeout(time.Minute)) }) When("controlled object doesn't have a controller reference", func() { var uncontrolledObj *corev1.ConfigMap BeforeEach(func(ctx SpecContext) { uncontrolledObj = newObject(&corev1.ConfigMap{}) metav1.SetMetaDataLabel(&uncontrolledObj.ObjectMeta, controllerRing.LabelDrain(), "test") Expect(testClient.Create(ctx, uncontrolledObj)).To(Succeed()) }, NodeTimeout(time.Minute)) It("should not trigger assignments", func(ctx SpecContext) { Eventually(ctx, Object(controlledObj)).Should(Not(HaveLabel(controllerRing.LabelDrain()))) Consistently(ctx, Object(uncontrolledObj)).Should(HaveLabelWithValue(controllerRing.LabelDrain(), "test")) }, SpecTimeout(time.Minute)) }) }) When("the assigned shard becomes unavailable", func() { var newShard *coordinationv1.Lease BeforeEach(func() { metav1.SetMetaDataLabel(&mainObj.ObjectMeta, controllerRing.LabelShard(), availableShard.Name) metav1.SetMetaDataLabel(&controlledObj.ObjectMeta, controllerRing.LabelShard(), availableShard.Name) newShard = newLease() // overwrite key functions to prefer first shard DeferCleanup(overwriteKeyFuncs(keyForShard(availableShard.Name))) }) JustBeforeEach(func(ctx SpecContext) { Expect(testClient.Create(ctx, availableShard)).To(Succeed()) Expect(testClient.Create(ctx, newShard)).To(Succeed()) }, NodeTimeout(time.Minute)) It("should immediately move the objects", func(ctx SpecContext) { By("assigned shard is still available") Consistently(ctx, Object(mainObj)).Should(HaveLabelWithValue(controllerRing.LabelShard(), availableShard.Name)) Consistently(ctx, Object(controlledObj)).Should(HaveLabelWithValue(controllerRing.LabelShard(), availableShard.Name)) By("assigned shard becomes unavailable") Eventually(ctx, Update(availableShard, func() { availableShard.Spec.HolderIdentity = nil })).Should(Succeed()) Eventually(ctx, Object(mainObj)).Should(And( Not(HaveLabel(controllerRing.LabelShard())), Not(HaveLabel(controllerRing.LabelDrain())), )) Eventually(ctx, Object(controlledObj)).Should(And( Not(HaveLabel(controllerRing.LabelShard())), Not(HaveLabel(controllerRing.LabelDrain())), )) }, SpecTimeout(time.Minute)) }) When("another shard becomes available", func() { var newShard *coordinationv1.Lease BeforeEach(func() { metav1.SetMetaDataLabel(&mainObj.ObjectMeta, controllerRing.LabelShard(), availableShard.Name) metav1.SetMetaDataLabel(&controlledObj.ObjectMeta, controllerRing.LabelShard(), availableShard.Name) newShard = newLease() newShard.Spec.HolderIdentity = nil // overwrite key functions to prefer new shard DeferCleanup(overwriteKeyFuncs(keyForShard(newShard.Name))) }) JustBeforeEach(func(ctx SpecContext) { Expect(testClient.Create(ctx, availableShard)).To(Succeed()) Expect(testClient.Create(ctx, newShard)).To(Succeed()) }, NodeTimeout(time.Minute)) It("should drain the main object and immediately move the controlled object", func(ctx SpecContext) { By("only one shard is available") Consistently(ctx, Object(mainObj)).Should(HaveLabelWithValue(controllerRing.LabelShard(), availableShard.Name)) Consistently(ctx, Object(controlledObj)).Should(HaveLabelWithValue(controllerRing.LabelShard(), availableShard.Name)) By("a new shard becomes available") Eventually(ctx, Update(newShard, func() { newShard.Spec.HolderIdentity = ptr.To(newShard.Name) })).Should(Succeed()) Eventually(ctx, Object(mainObj)).Should(And( HaveLabelWithValue(controllerRing.LabelShard(), availableShard.Name), HaveLabel(controllerRing.LabelDrain()), ), "should drain the main object") Eventually(ctx, Object(controlledObj)).Should(And( Not(HaveLabel(controllerRing.LabelShard())), Not(HaveLabel(controllerRing.LabelDrain())), ), "should move the controlled object") }, SpecTimeout(time.Minute)) }) }) func newObject[T client.Object](obj T) T { obj.SetName(testRunID + "-" + test.RandomSuffix()) obj.SetNamespace(testRunID) return obj } func newLease() *coordinationv1.Lease { name := testRunID + "-" + test.RandomSuffix() return &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: testRunID, Labels: map[string]string{ shardingv1alpha1.LabelControllerRing: controllerRing.Name, }, }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To(name), LeaseDurationSeconds: ptr.To[int32](10), AcquireTime: ptr.To(metav1.NewMicroTime(clock.Now().Add(-5 * time.Minute))), RenewTime: ptr.To(metav1.NewMicroTime(clock.Now().Add(-2 * time.Second))), }, } } func overwriteKeyFuncs(fn key.Func) func() { origObject, origController := sharder.KeyForObject, sharder.KeyForController sharder.KeyForObject, sharder.KeyForController = fn, fn return func() { sharder.KeyForObject, sharder.KeyForController = origObject, origController } } // keyForShard returns a key.Func that prefers assigning all objects to the shard with the given name. // This is done by returning the key used for the first virtual node of the shard. func keyForShard(shardName string) key.Func { return func(obj client.Object) (string, error) { return shardName + "0", nil } } ================================================ FILE: test/integration/sharder/controller/shardlease/shardlease_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package shardlease_test import ( "context" "testing" "time" "github.com/go-logr/logr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" testclock "k8s.io/utils/clock/testing" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" "sigs.k8s.io/controller-runtime/pkg/envtest/komega" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/controller/shardlease" utilclient "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/client" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) func TestShardLease(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Sharder Shard Lease Controller Integration Test Suite") } const testID = "shardlease-controller-test" var ( log logr.Logger testClient client.Client clock *testclock.FakeClock testRunID string testRunLabels map[string]string ) var _ = BeforeSuite(func(ctx SpecContext) { logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter))) log = logf.Log.WithName(testID) By("Start test environment") testEnv := &envtest.Environment{ CRDInstallOptions: envtest.CRDInstallOptions{ Paths: []string{test.PathShardingCRDs()}, }, ErrorIfCRDPathMissing: true, } restConfig, err := testEnv.Start() Expect(err).NotTo(HaveOccurred()) Expect(restConfig).NotTo(BeNil()) DeferCleanup(func() { By("Stop test environment") Expect(testEnv.Stop()).To(Succeed()) }) By("Create test clients") testClient, err = client.New(restConfig, client.Options{Scheme: utilclient.SharderScheme}) Expect(err).NotTo(HaveOccurred()) Expect(testClient).NotTo(BeNil()) clientContext, clientCancel := context.WithCancel(context.Background()) komega.SetClient(testClient) komega.SetContext(clientContext) DeferCleanup(clientCancel) By("Create test Namespace") testNamespace := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ GenerateName: testID + "-", }, } Expect(testClient.Create(ctx, testNamespace)).To(Succeed()) log.Info("Created Namespace for test", "namespaceName", testNamespace.Name) testRunID = testNamespace.Name log = log.WithValues("testRunID", testRunID) testRunLabels = map[string]string{testID: testRunID} DeferCleanup(func(ctx SpecContext) { By("Delete test Namespace") Expect(testClient.Delete(ctx, testNamespace)).To(Or(Succeed(), BeNotFoundError())) }, NodeTimeout(time.Minute)) By("Setup manager") mgr, err := manager.New(restConfig, manager.Options{ Scheme: utilclient.SharderScheme, Metrics: metricsserver.Options{BindAddress: "0"}, Cache: cache.Options{ DefaultNamespaces: map[string]cache.Config{testNamespace.Name: {}}, ByObject: map[client.Object]cache.ByObject{ &shardingv1alpha1.ControllerRing{}: { Label: labels.SelectorFromSet(testRunLabels), }, }, }, }) Expect(err).NotTo(HaveOccurred()) By("Register controller") clock = testclock.NewFakeClock(time.Now()) Expect((&shardlease.Reconciler{ Clock: clock, }).AddToManager(mgr)).To(Succeed()) By("Start manager") mgrContext, mgrCancel := context.WithCancel(context.Background()) go func() { defer GinkgoRecover() Expect(mgr.Start(mgrContext)).To(Succeed()) }() DeferCleanup(func() { By("Stop manager") mgrCancel() }) }, NodeTimeout(time.Minute)) ================================================ FILE: test/integration/sharder/controller/shardlease/shardlease_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package shardlease_test import ( "maps" "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" gomegatypes "github.com/onsi/gomega/types" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" . "sigs.k8s.io/controller-runtime/pkg/envtest/komega" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) var _ = Describe("Shard Lease controller", func() { var ( controllerRing *shardingv1alpha1.ControllerRing lease *coordinationv1.Lease ) BeforeEach(func(ctx SpecContext) { controllerRing = &shardingv1alpha1.ControllerRing{ ObjectMeta: metav1.ObjectMeta{ GenerateName: testRunID + "-", Labels: maps.Clone(testRunLabels), }, Spec: shardingv1alpha1.ControllerRingSpec{ Resources: []shardingv1alpha1.RingResource{ { GroupResource: metav1.GroupResource{Group: "apps", Resource: "deployments"}, }, }, }, } Expect(testClient.Create(ctx, controllerRing)).To(Succeed()) log.Info("Created ControllerRing for test", "controllerRingName", controllerRing.Name) DeferCleanup(func(ctx SpecContext) { Expect(testClient.Delete(ctx, controllerRing)).To(Or(Succeed(), BeNotFoundError())) }, NodeTimeout(time.Minute)) name := testRunID + "-" + test.RandomSuffix() lease = &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: testRunID, Labels: map[string]string{ shardingv1alpha1.LabelControllerRing: controllerRing.Name, }, }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To(name), LeaseDurationSeconds: ptr.To[int32](10), AcquireTime: ptr.To(metav1.NewMicroTime(clock.Now().Add(-5 * time.Minute))), RenewTime: ptr.To(metav1.NewMicroTime(clock.Now().Add(-2 * time.Second))), }, } Expect(testClient.Create(ctx, lease)).To(Succeed()) log.Info("Created Lease for test", "leaseName", lease.Name) }, NodeTimeout(time.Minute), OncePerOrdered) Describe("should reflect the shard state in the label", Ordered, func() { It("shard is ready", func(ctx SpecContext) { Eventually(ctx, Object(lease)).Should(haveState("ready")) }, SpecTimeout(time.Minute)) It("lease is expired", func(ctx SpecContext) { clock.Step(8 * time.Second) Eventually(ctx, Object(lease)).Should(haveState("expired")) }, SpecTimeout(time.Minute)) It("expired lease is renewed", func(ctx SpecContext) { clock.Step(8 * time.Second) Eventually(ctx, Object(lease)).Should(haveState("expired")) Eventually(ctx, Update(lease, func() { lease.Spec.RenewTime = ptr.To(metav1.NewMicroTime(clock.Now())) })).Should(Succeed()) Eventually(ctx, Object(lease)).Should(haveState("ready")) }, SpecTimeout(time.Minute)) It("should acquire expired lease that is not renewed", func(ctx SpecContext) { clock.Step(10 * time.Second) Eventually(ctx, Object(lease)).Should(haveState("expired")) clock.Step(10 * time.Second) Eventually(ctx, Object(lease)).Should(And( haveState("dead"), HaveField("Spec.HolderIdentity", HaveValue(Equal("shardlease-controller"))), HaveField("Spec.LeaseDurationSeconds", HaveValue(BeEquivalentTo(20))), HaveField("Spec.AcquireTime.Time", BeTemporally("~", clock.Now())), HaveField("Spec.RenewTime.Time", BeTemporally("~", clock.Now())), HaveField("Spec.LeaseTransitions", HaveValue(BeEquivalentTo(1))), )) }, SpecTimeout(time.Minute)) It("dead lease is renewed", func(ctx SpecContext) { Eventually(ctx, Update(lease, func() { lease.Spec.HolderIdentity = ptr.To(lease.Name) lease.Spec.LeaseDurationSeconds = ptr.To[int32](10) lease.Spec.AcquireTime = ptr.To(metav1.NewMicroTime(clock.Now())) lease.Spec.RenewTime = ptr.To(metav1.NewMicroTime(clock.Now())) *lease.Spec.LeaseTransitions++ })).Should(Succeed()) Eventually(ctx, Object(lease)).Should(haveState("ready")) }, SpecTimeout(time.Minute)) It("should garbage collect orphaned leases", func(ctx SpecContext) { clock.Step(20 * time.Second) Eventually(ctx, Object(lease)).Should(haveState("dead")) clock.Step(20*time.Second + time.Minute) Eventually(ctx, Get(lease)).Should(BeNotFoundError()) }, SpecTimeout(time.Minute)) }) }) func haveState(state string) gomegatypes.GomegaMatcher { return HaveLabelWithValue("alpha.sharding.timebertt.dev/state", state) } ================================================ FILE: test/integration/sharder/webhook/sharder/sharder_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package sharder_test import ( "context" "maps" "testing" "time" "github.com/go-logr/logr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" testclock "k8s.io/utils/clock/testing" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" "sigs.k8s.io/controller-runtime/pkg/envtest/komega" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" configv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/config/v1alpha1" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/controller/controllerring" utilclient "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/client" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" "github.com/timebertt/kubernetes-controller-sharding/pkg/webhook/sharder" ) func TestSharder(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Sharder Webhook Integration Test Suite") } const testID = "sharder-webhook-test" var ( log logr.Logger testClient client.Client mgrClient client.Client clock *testclock.FakeClock testRunID string testRunLabels map[string]string controllerRing *shardingv1alpha1.ControllerRing ) var _ = BeforeSuite(func(ctx SpecContext) { logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter))) log = logf.Log.WithName(testID) testRunID = testID + "-" + test.RandomSuffix() testRunLabels = map[string]string{testID: testRunID} controllerRing = &shardingv1alpha1.ControllerRing{ ObjectMeta: metav1.ObjectMeta{ Name: testRunID, Labels: maps.Clone(testRunLabels), }, Spec: shardingv1alpha1.ControllerRingSpec{ Resources: []shardingv1alpha1.RingResource{{ GroupResource: metav1.GroupResource{Group: "", Resource: "configmaps"}, ControlledResources: []metav1.GroupResource{{Group: "", Resource: "secrets"}}, }}, }, } webhookConfig := controllerring.WebhookConfigForControllerRing(controllerRing, &configv1alpha1.WebhookConfig{ ClientConfig: &admissionregistrationv1.WebhookClientConfig{ // the path will be set by the called function, and envtest will transform it to the proper URL Service: &admissionregistrationv1.ServiceReference{}, }, NamespaceSelector: &metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{{ Key: corev1.LabelMetadataName, Operator: metav1.LabelSelectorOpIn, Values: []string{testRunID}, }}, }, }) By("Start test environment") testEnv := &envtest.Environment{ CRDInstallOptions: envtest.CRDInstallOptions{ Paths: []string{test.PathShardingCRDs()}, }, ErrorIfCRDPathMissing: true, WebhookInstallOptions: envtest.WebhookInstallOptions{ MutatingWebhooks: []*admissionregistrationv1.MutatingWebhookConfiguration{webhookConfig}, }, } if test.UseExistingCluster() { // NB: envtest does a lookup and complains if it cannot resolve this host. Add a dummy entry to /etc/host as a // workaround. testEnv.WebhookInstallOptions.LocalServingHostExternalName = "host.docker.internal" DeferCleanup(func(ctx SpecContext) { Expect(testClient.Delete(ctx, webhookConfig)).To(Succeed()) }, NodeTimeout(time.Minute)) } restConfig, err := testEnv.Start() Expect(err).NotTo(HaveOccurred()) Expect(restConfig).NotTo(BeNil()) DeferCleanup(func() { By("Stop test environment") Expect(testEnv.Stop()).To(Succeed()) }) By("Create test clients") testClient, err = client.New(restConfig, client.Options{Scheme: utilclient.SharderScheme}) Expect(err).NotTo(HaveOccurred()) Expect(testClient).NotTo(BeNil()) clientContext, clientCancel := context.WithCancel(context.Background()) komega.SetClient(testClient) komega.SetContext(clientContext) DeferCleanup(clientCancel) By("Create test Namespace") testNamespace := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: testRunID, }, } Expect(testClient.Create(ctx, testNamespace)).To(Succeed()) log.Info("Created Namespace for test", "namespaceName", testNamespace.Name) log = log.WithValues("testRunID", testRunID) DeferCleanup(func(ctx SpecContext) { By("Delete test Namespace") Expect(testClient.Delete(ctx, testNamespace)).To(Or(Succeed(), BeNotFoundError())) }, NodeTimeout(time.Minute)) By("Create ControllerRing") Expect(testClient.Create(ctx, controllerRing)).To(Succeed()) log.Info("Created ControllerRing for test", "controllerRingName", controllerRing.Name) DeferCleanup(func(ctx SpecContext) { Expect(testClient.Delete(ctx, controllerRing)).To(Or(Succeed(), BeNotFoundError())) }, NodeTimeout(time.Minute)) By("Setup manager") mgr, err := manager.New(restConfig, manager.Options{ Scheme: utilclient.SharderScheme, Metrics: metricsserver.Options{BindAddress: "0"}, WebhookServer: webhook.NewServer(webhook.Options{ Port: testEnv.WebhookInstallOptions.LocalServingPort, Host: testEnv.WebhookInstallOptions.LocalServingHost, CertDir: testEnv.WebhookInstallOptions.LocalServingCertDir, }), Cache: cache.Options{ DefaultNamespaces: map[string]cache.Config{testNamespace.Name: {}}, ByObject: map[client.Object]cache.ByObject{ &shardingv1alpha1.ControllerRing{}: { Label: labels.SelectorFromSet(testRunLabels), }, }, }, }) Expect(err).NotTo(HaveOccurred()) mgrClient = mgr.GetClient() By("Register webhook") clock = testclock.NewFakeClock(time.Now()) Expect((&sharder.Handler{ Clock: clock, }).AddToManager(mgr)).To(Succeed()) By("Start manager") mgrContext, mgrCancel := context.WithCancel(context.Background()) go func() { defer GinkgoRecover() Expect(mgr.Start(mgrContext)).To(Succeed()) }() DeferCleanup(func() { By("Stop manager") mgrCancel() }) }, NodeTimeout(time.Minute)) ================================================ FILE: test/integration/sharder/webhook/sharder/sharder_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package sharder_test import ( "context" "maps" "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" gomegatypes "github.com/onsi/gomega/types" coordinationv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" . "sigs.k8s.io/controller-runtime/pkg/envtest/komega" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" ) var _ = Describe("Shard Lease controller", func() { var ( mainObj *corev1.ConfigMap availableShard, deadShard *coordinationv1.Lease ) BeforeEach(func(ctx SpecContext) { mainObj = &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "test-" + test.RandomSuffix(), Namespace: testRunID, Labels: maps.Clone(testRunLabels), }, } availableShard = newLease() Expect(testClient.Create(ctx, availableShard)).To(Succeed()) deadShard = newLease() deadShard.Spec.HolderIdentity = nil Expect(testClient.Create(ctx, deadShard)).To(Succeed()) DeferCleanup(func(ctx SpecContext) { // clean up all leases from this test case Expect(testClient.DeleteAllOf(ctx, &coordinationv1.Lease{}, client.InNamespace(testRunID))).To(Succeed()) // wait until the manager no longer sees leases from this test case Eventually(ctx, New(mgrClient).ObjectList(&coordinationv1.LeaseList{}, client.InNamespace(testRunID))).Should(HaveField("Items", BeEmpty())) }, NodeTimeout(time.Minute)) }, NodeTimeout(time.Minute)) Describe("main resource", func() { It("should assign the object during creation", func(ctx SpecContext) { Eventually(ctx, createObject(mainObj)).Should(beAssigned(availableShard.Name)) }, SpecTimeout(time.Minute)) It("should fail due to unsupported generateName", func(ctx SpecContext) { mainObj.Name = "" mainObj.GenerateName = "test-" Eventually(ctx, func(ctx context.Context) error { return testClient.Create(ctx, mainObj, client.DryRunAll) }).Should(MatchError(ContainSubstring("generateName is not supported"))) }, SpecTimeout(time.Minute)) When("the assigned shard gets unavailable", func() { var ( assignedShard, otherShard *coordinationv1.Lease ) BeforeEach(func(ctx SpecContext) { Eventually(ctx, createObject(mainObj)).Should(beAssigned(availableShard.Name)) Eventually(ctx, Update(availableShard, func() { availableShard.Spec.HolderIdentity = nil })).Should(Succeed()) assignedShard = availableShard Eventually(ctx, Update(deadShard, func() { deadShard.Spec.HolderIdentity = ptr.To(deadShard.Name) })).Should(Succeed()) otherShard = deadShard }, NodeTimeout(time.Minute)) It("should not reassign the object during update", func(ctx SpecContext) { Consistently(ctx, patchObject(mainObj)).Should(beAssigned(assignedShard.Name)) }) It("should reassign the object during drain", func(ctx SpecContext) { Eventually(ctx, drainObject(mainObj)).Should(beAssigned(otherShard.Name)) }) }) }) Describe("controlled resource", func() { var controlledObj *corev1.Secret BeforeEach(func(ctx SpecContext) { Eventually(ctx, createObject(mainObj)).Should(beAssigned(availableShard.Name)) controlledObj = &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "test-" + test.RandomSuffix(), Namespace: testRunID, Labels: maps.Clone(testRunLabels), }, } Expect(controllerutil.SetControllerReference(mainObj, controlledObj, testClient.Scheme())).To(Succeed()) }, NodeTimeout(time.Minute)) It("should assign the object during creation", func(ctx SpecContext) { Eventually(ctx, createObject(controlledObj)).Should(beAssigned(availableShard.Name)) }, SpecTimeout(time.Minute)) It("should assign the object during creation with generateName", func(ctx SpecContext) { controlledObj.Name = "" controlledObj.GenerateName = "test-" Eventually(ctx, createObject(controlledObj)).Should(beAssigned(availableShard.Name)) }, SpecTimeout(time.Minute)) It("should not assign an object without controller reference", func(ctx SpecContext) { controlledObj.OwnerReferences = nil Consistently(ctx, createObject(controlledObj, client.DryRunAll)).ShouldNot(beAssigned()) }, SpecTimeout(time.Minute)) When("the assigned shard gets unavailable", func() { var ( assignedShard, otherShard *coordinationv1.Lease ) BeforeEach(func(ctx SpecContext) { Eventually(ctx, createObject(controlledObj)).Should(beAssigned(availableShard.Name)) Eventually(ctx, Update(availableShard, func() { availableShard.Spec.HolderIdentity = nil })).Should(Succeed()) assignedShard = availableShard Eventually(ctx, Update(deadShard, func() { deadShard.Spec.HolderIdentity = ptr.To(deadShard.Name) })).Should(Succeed()) otherShard = deadShard }, NodeTimeout(time.Minute)) It("should not reassign the object during update", func(ctx SpecContext) { Consistently(ctx, patchObject(controlledObj)).Should(beAssigned(assignedShard.Name)) }) It("should reassign the object during drain", func(ctx SpecContext) { Eventually(ctx, drainObject(controlledObj)).Should(beAssigned(otherShard.Name)) }) }) }) }) func newLease() *coordinationv1.Lease { name := testRunID + "-" + test.RandomSuffix() return &coordinationv1.Lease{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: testRunID, Labels: map[string]string{ shardingv1alpha1.LabelControllerRing: controllerRing.Name, }, }, Spec: coordinationv1.LeaseSpec{ HolderIdentity: ptr.To(name), LeaseDurationSeconds: ptr.To[int32](10), AcquireTime: ptr.To(metav1.NewMicroTime(clock.Now().Add(-5 * time.Minute))), RenewTime: ptr.To(metav1.NewMicroTime(clock.Now().Add(-2 * time.Second))), }, } } func beAssigned(shard ...string) gomegatypes.GomegaMatcher { if len(shard) == 0 { return HaveLabel("shard.alpha.sharding.timebertt.dev/" + controllerRing.Name) } return HaveLabelWithValue("shard.alpha.sharding.timebertt.dev/"+controllerRing.Name, shard[0]) } func createObject(obj client.Object, opts ...client.CreateOption) func(ctx context.Context) (client.Object, error) { return func(ctx context.Context) (client.Object, error) { obj.SetResourceVersion("") err := testClient.Create(ctx, obj, opts...) if apierrors.IsAlreadyExists(err) { return obj, StopTrying(err.Error()) } return obj, err } } func patchObject(obj client.Object) func(ctx context.Context) (client.Object, error) { return func(ctx context.Context) (client.Object, error) { return obj, testClient.Patch(ctx, obj, client.RawPatch(types.MergePatchType, []byte("{}"))) } } func drainObject(obj client.Object) func(ctx context.Context) (client.Object, error) { patch := client.MergeFrom(obj.DeepCopyObject().(client.Object)) labels := obj.GetLabels() delete(labels, "shard.alpha.sharding.timebertt.dev/"+controllerRing.Name) obj.SetLabels(labels) return func(ctx context.Context) (client.Object, error) { return obj, testClient.Patch(ctx, obj, patch) } } ================================================ FILE: webhosting-operator/PROJECT ================================================ componentConfig: true domain: timebertt.dev layout: - go.kubebuilder.io/v3 multigroup: true projectName: webhosting-operator repo: github.com/timebertt/kubernetes-controller-sharding/webhosting-operator resources: - api: crdVersion: v1 namespaced: true controller: true domain: timebertt.dev group: webhosting kind: Website path: github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/apis/webhosting/v1alpha1 version: v1alpha1 - api: crdVersion: v1 controller: true domain: timebertt.dev group: webhosting kind: Theme path: github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/apis/webhosting/v1alpha1 version: v1alpha1 - api: crdVersion: v1 namespaced: true domain: webhosting.timebertt.dev group: config kind: WebhostingOperatorConfig path: github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/apis/config/v1alpha1 version: v1alpha1 version: "3" ================================================ FILE: webhosting-operator/README.md ================================================ # webhosting-operator webhosting-operator is a simple operator developed using [kubebuilder](https://github.com/kubernetes-sigs/kubebuilder). It is built for demonstrating and evaluating the implemented sharding mechanisms for Kubernetes controllers, see [Evaluating the Sharding Mechanism](../docs/evaluation.md). The webhosting-operator is developed in a dedicated Go module so that its dependencies don't leak into the main module which also contains the shard library. The webhosting-operator reuses the sharder components from the shard library as described in [Implement Sharding in Your Controller](../docs/implement-sharding.md). For now, the webhosting-operator is kept in the same repository for simple evaluation of the project. However, it might be extracted into a dedicated repository later on if necessary. ## Sample Operator Requirements To demonstrate and evaluate the proposed sharding design, an operator is needed that fulfills the following requirements: - it should be composed of a single controller for one (custom) resource - in addition to watching its own resources, it needs to watch other relevant objects (e.g. owned objects) as well - sharding is more difficult here, so add it as a challenge - it needs to deal with cluster-scoped objects (that are relevant for multiple namespaced objects) - this adds side effects (duplicated cache) which need to be taken care of ## Idea / Introduction The idea behind this operator is simple: we want to build a web hosting platform on top of Kubernetes. I.e., we want to be able to configure websites for our customers in a declarative manner. The desired state is configured via Kubernetes (custom) resources and the operator takes care to spin up websites and expose them. There are three resources involved: - `Namespace` - each customer project gets its own namespace - a project namespace is identified by the `webhosting.timebertt.dev/project=true` label - `Theme` (API group `webhosting.timebertt.dev`, cluster-scoped) - represents an offered theme for customer websites (managed by service admin) - configures a font family and color for websites - `Website` (API group `webhosting.timebertt.dev`, namespaced) - represents a single website a customer orders (managed by the customer in a project namespace) - website simply displays the website's name (static) - each website references exactly one theme - deploys and configures a simple `nginx` deployment - exposes the website via service and ingress ## Setup To test controller sharding with the webhosting-operator as an example controller, see [Evaluation](../docs/evaluation.md). ================================================ FILE: webhosting-operator/cmd/experiment/main.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package main import ( "context" "flag" "fmt" "os" "time" "github.com/go-logr/logr" "github.com/spf13/cobra" "go.uber.org/zap/zapcore" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. _ "k8s.io/client-go/plugin/pkg/client/auth" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/utils" // Import all scenarios _ "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/scenario/all" ) var ( log logr.Logger scheme = runtime.NewScheme() ) func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(webhostingv1alpha1.AddToScheme(scheme)) } func main() { zapOpts := zap.Options{ TimeEncoder: zapcore.ISO8601TimeEncoder, } var ( mgr manager.Manager selectedScenario experiment.Scenario ) cmd := &cobra.Command{ Use: "experiment", Args: cobra.NoArgs, SilenceErrors: true, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { cmd.SilenceUsage = true ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zapOpts))) log = ctrl.Log klog.SetLogger(ctrl.Log) var err error mgr, err = ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ Scheme: scheme, HealthProbeBindAddress: ":8081", Metrics: metricsserver.Options{ BindAddress: ":8080", }, // disable leader election LeaderElection: false, }) if err != nil { return err } if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { return fmt.Errorf("unable to set up health check: %w", err) } if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { return fmt.Errorf("unable to set up ready check: %w", err) } return nil }, PersistentPostRunE: func(cmd *cobra.Command, args []string) error { if err := selectedScenario.AddToManager(mgr); err != nil { return err } ctx, cancel := context.WithCancel(cmd.Context()) defer cancel() go func() { select { case <-ctx.Done(): case <-selectedScenario.Done(): // stop the manager when scenario is done if utils.RunningInCluster() { // but give monitoring a bit more time to scrape the final metrics values if running in a cluster <-time.After(time.Minute) } cancel() } }() log.Info("Starting manager") return mgr.Start(ctx) }, } zapOpts.BindFlags(flag.CommandLine) cmd.PersistentFlags().AddGoFlagSet(flag.CommandLine) group := cobra.Group{ ID: "scenarios", Title: "Available Scenarios", } cmd.AddGroup(&group) for _, scenario := range experiment.GetAllScenarios() { cmd.AddCommand(&cobra.Command{ Use: scenario.Name(), Short: scenario.Description(), Long: scenario.LongDescription(), Args: cobra.NoArgs, GroupID: group.ID, Run: func(cmd *cobra.Command, args []string) { selectedScenario = scenario }, }) } if err := cmd.ExecuteContext(ctrl.SetupSignalHandler()); err != nil { fmt.Printf("Error running experiment: %v\n", err) os.Exit(1) } } ================================================ FILE: webhosting-operator/cmd/measure/main.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package main import ( "context" "encoding/csv" "fmt" "io" "math" "os" "path/filepath" "slices" "strconv" "strings" "time" "github.com/prometheus/client_golang/api" "github.com/prometheus/client_golang/api/prometheus/v1" "github.com/prometheus/common/model" "github.com/spf13/cobra" "gopkg.in/yaml.v3" "k8s.io/apimachinery/pkg/util/sets" "sigs.k8s.io/controller-runtime/pkg/manager/signals" ) const ( stdin = "-" stdout = "-" ) var ( now = time.Now() queriesInput io.Reader outputDir string outputPrefix string prometheusURL = "http://localhost:9091" queryRange = v1.Range{ Start: now.Add(-15 * time.Minute), End: now, Step: 15 * time.Second, } ) func main() { cmd := &cobra.Command{ Use: "measure QUERIES_FILE|-", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { queriesFileName := args[0] if queriesFileName == stdin { queriesInput = os.Stdin } else { file, err := os.Open(queriesFileName) if err != nil { return err } defer file.Close() queriesInput = file } c, err := newClient() if err != nil { return fmt.Errorf("error creating prometheus client: %w", err) } cmd.SilenceUsage = true return run(cmd.Context(), c) }, } cmd.Flags().StringVarP(&outputDir, "output-dir", "o", outputDir, "Directory to write output files to, - for stdout (defaults to working directory)") cmd.Flags().StringVar(&outputPrefix, "output-prefix", outputPrefix, "Prefix to prepend to all output files") cmd.Flags().StringVar(&prometheusURL, "prometheus-url", prometheusURL, "URL for querying prometheus") cmd.Flags().DurationVar(&queryRange.Step, "step", queryRange.Step, "Query resolution step width") cmd.Flags().Var((*timeValue)(&queryRange.Start), "start", "Query start timestamp (RFC3339/duration relative to now/unix timestamp in seconds), inclusive (defaults to now-15m)") cmd.Flags().Var((*timeValue)(&queryRange.End), "end", "Query end timestamp (RFC3339/duration relative to now/unix timestamp in seconds), inclusive (defaults to now)") if err := cmd.ExecuteContext(signals.SetupSignalHandler()); err != nil { os.Exit(1) } } // timeValue implements pflag.Value for specifying a timestamp in one of the following formats: // - RFC3339, e.g. 2006-01-02T15:04:05Z07:00 // - duration relative to now, e.g. -5m // - unix timestamp in seconds, e.g. 1665825136 type timeValue time.Time func (t *timeValue) Type() string { return "time" } func (t *timeValue) String() string { return (*time.Time)(t).UTC().Format(time.RFC3339) } func (t *timeValue) Set(s string) error { // first try RFC3339 timestamp tt, err := time.Parse(time.RFC3339, s) if err == nil { *t = timeValue(tt) return nil } // then try duration dd, err := time.ParseDuration(s) if err == nil { *t = timeValue(time.Now().Add(dd)) return nil } // lastly try unix timestamp ii, err := strconv.ParseInt(s, 10, 64) if err == nil { *t = timeValue(time.Unix(ii, 0)) return nil } return fmt.Errorf("invalid time value: %q", s) } func newClient() (v1.API, error) { apiClient, err := api.NewClient(api.Config{ Address: prometheusURL, }) if err != nil { return nil, err } return v1.NewAPI(apiClient), nil } const ( QueryTypeInstant = "instant" QueryTypeRange = "range" ) type QueriesConfig struct { Queries []Query `yaml:"queries"` } type Query struct { Name string `yaml:"name"` // range or instant, defaults to range. // If instant is specified, the $__range variable in the query is substituted by the configured range's duration. Type string `yaml:"type,omitempty"` Query string `yaml:"query"` Optional bool `yaml:"optional,omitempty"` // upper threshold for values SLO *float64 `yaml:"slo,omitempty"` } func run(ctx context.Context, c v1.API) error { config, err := decodeQueriesConfig() if err != nil { return fmt.Errorf("error decoding queries file: %w", err) } if err = prepareOutputDir(); err != nil { return err } fmt.Printf("Using time range for query: %s\n", rangeToString(queryRange)) var ( slosChecked = false slosMet = true ) for _, q := range config.Queries { data, err := q.fetchData(ctx, c) if err != nil { return fmt.Errorf("error fetching data for query %q: %w", q.Name, err) } if data.IsEmpty() { if q.Optional { fmt.Printf("Skipping output for query %q as data is empty\n", q.Name) continue } return fmt.Errorf("data is empty for query %q, but query is required", q.Name) } if err = q.writeResult(data); err != nil { return fmt.Errorf("error writing result: %w", err) } if checked, ok := q.verifySLO(data); checked { slosChecked = true if !ok { slosMet = false } } } if slosChecked { if !slosMet { return fmt.Errorf("❌ SLO verifications failed") } fmt.Println("✅ SLO verifications succeeded") } else { fmt.Println("ℹ️ No SLOs defined") } return nil } func decodeQueriesConfig() (*QueriesConfig, error) { configData, err := io.ReadAll(queriesInput) if err != nil { return nil, err } c := &QueriesConfig{} return c, yaml.Unmarshal(configData, c) } func prepareOutputDir() error { if outputDir == stdout { return nil } if outputDir == "" { outputDir = "." } if err := os.MkdirAll(outputDir, 0750); err != nil { return err } fmt.Printf("Writing output files to %s\n", outputDir) return nil } func (q Query) fetchData(ctx context.Context, c v1.API) (metricData, error) { opts := []v1.Option{v1.WithTimeout(10 * time.Second)} var ( data metricData result model.Value warnings v1.Warnings err error ) switch q.Type { case QueryTypeRange, "": result, warnings, err = c.QueryRange(ctx, q.Query, queryRange, opts...) if err != nil { return nil, err } matrix, ok := result.(model.Matrix) if !ok { return nil, fmt.Errorf("unexpected value type %q for query %q, expected matrix", result.Type().String(), q.Name) } data = &matrixData{Matrix: matrix} case QueryTypeInstant: rangeString := queryRange.End.Sub(queryRange.Start).String() query := q.Query query = strings.ReplaceAll(query, "$__range", rangeString) result, warnings, err = c.Query(ctx, query, queryRange.End, opts...) if err != nil { return nil, err } vector, ok := result.(model.Vector) if !ok { return nil, fmt.Errorf("unexpected value type %q for query %q, expected vector", result.Type().String(), q.Name) } data = &vectorData{Vector: vector} default: return nil, fmt.Errorf("unsupported query type %q", q.Type) } if len(warnings) > 0 { fmt.Printf("Warnings: %v\n", warnings) } return data, nil } func (q Query) writeResult(data metricData) error { fileName := outputPrefix + q.Name + ".csv" var out io.Writer if outputDir == stdout { out = os.Stdout fmt.Println("# " + fileName) } else { file, err := os.OpenFile(filepath.Join(outputDir, fileName), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return err } defer file.Close() out = file } // go maps are unsorted -> need to sort labels by name so that all values end up in the right column labelNames := data.GetLabelNames() slices.Sort(labelNames) // write header w := csv.NewWriter(out) if err := w.Write(append([]string{"ts", "value"}, toStringSlice(labelNames)...)); err != nil { return err } // write contents data.Reset() for { value := data.NextValue() if value.IsZero() { // end of results break } labelValues := make([]string, len(labelNames)) for i, name := range labelNames { labelValues[i] = string(value.metric[name]) } if err := w.Write(append([]string{ strconv.FormatInt(value.time.Unix(), 10), strconv.FormatFloat(value.value, 'f', -1, 64), }, labelValues...)); err != nil { return err } } w.Flush() if err := w.Error(); err != nil { return err } fmt.Printf("Successfully written output to %s\n", fileName) return nil } func (q Query) verifySLO(data metricData) (checked bool, ok bool) { if q.SLO == nil { return false, true } var allFailures []string data.Reset() for { value := data.NextValue() if value.IsZero() { // end of results break } if math.IsNaN(value.value) || value.value <= *q.SLO { continue } allFailures = append(allFailures, fmt.Sprintf("%s => %f @[%s]", value.metric, value.value, value.time.Format(time.RFC3339))) } if len(allFailures) > 0 { indent := "- " fmt.Printf("❌ SLO for query %q (<= %f) is not met:\n%s\n", q.Name, *q.SLO, indent+strings.Join(allFailures, "\n"+indent)) return true, false } fmt.Printf("✅ SLO for query %q (<= %f) met\n", q.Name, *q.SLO) return true, true } func rangeToString(r v1.Range) string { return fmt.Sprintf("start:%s end:%s step:%s", r.Start.UTC().Format(time.RFC3339), r.End.UTC().Format(time.RFC3339), r.Step.String()) } // metricData gives cursor-style access to metric values, which could either be a matrix (for range queries) or a vector // (for instant queries). type metricData interface { // IsEmpty returns true if the query result was empty. IsEmpty() bool // GetLabelNames returns an unsorted list of label names of the first metric. GetLabelNames() model.LabelNames // Reset resets the cursor. Reset() // NextValue moves the cursor to the next metric value and returns it. It returns a zero metricValue at the end. NextValue() metricValue } type metricValue struct { metric model.Metric time time.Time value float64 } func (m metricValue) IsZero() bool { return m.time.IsZero() } type matrixData struct { model.Matrix cursor struct { metric, value int } } func (m *matrixData) IsEmpty() bool { return m.Len() == 0 } func (m *matrixData) GetLabelNames() model.LabelNames { labels := sets.New[model.LabelName]() for _, metric := range m.Matrix { for labelName := range metric.Metric { if labelName == model.MetricNameLabel { continue } labels.Insert(labelName) } } return labels.UnsortedList() } func (m *matrixData) Reset() { m.cursor.metric = 0 m.cursor.value = 0 } func (m *matrixData) NextValue() metricValue { if m.IsEmpty() { return metricValue{} } // move to next metric if we already visited all values in the current metric if m.cursor.value >= len(m.Matrix[m.cursor.metric].Values) { m.cursor.metric++ m.cursor.value = 0 } // end of results if m.cursor.metric >= m.Len() { return metricValue{} } sampleStream := m.Matrix[m.cursor.metric] value := sampleStream.Values[m.cursor.value] // move on to the next value in the current metric m.cursor.value++ return metricValue{ metric: sampleStream.Metric, time: value.Timestamp.Time(), value: float64(value.Value), } } type vectorData struct { model.Vector cursor int } func (v *vectorData) IsEmpty() bool { return v.Len() == 0 } func (v *vectorData) GetLabelNames() model.LabelNames { labels := sets.New[model.LabelName]() for _, metric := range v.Vector { for labelName := range metric.Metric { if labelName == model.MetricNameLabel { continue } labels.Insert(labelName) } } return labels.UnsortedList() } func (v *vectorData) Reset() { v.cursor = 0 } func (v *vectorData) NextValue() metricValue { if v.IsEmpty() { return metricValue{} } // end of results if v.cursor >= len(v.Vector) { return metricValue{} } sample := v.Vector[v.cursor] // move on to the next sample v.cursor++ return metricValue{ metric: sample.Metric, time: sample.Timestamp.Time(), value: float64(sample.Value), } } func toStringSlice[S ~[]E, E ~string](s S) []string { out := make([]string, 0, len(s)) for _, v := range s { out = append(out, string(v)) } return out } ================================================ FILE: webhosting-operator/cmd/measure/test.yaml ================================================ queries: - name: queue-rate-by-pod type: range # returns a matrix slo: 200 query: sum(rate(workqueue_adds_total{job="webhosting-operator"}[1m])) by (pod) - name: queue-latency-by-controller type: instant # returns a vector slo: 0.1 query: | histogram_quantile(0.99, sum by (name, le) (rate( workqueue_queue_duration_seconds_bucket{ job="webhosting-operator", }[$__range] )) ) ================================================ FILE: webhosting-operator/cmd/samples-generator/main.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package main import ( "context" "fmt" "math/rand" "os" "github.com/spf13/cobra" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager/signals" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. _ "k8s.io/client-go/plugin/pkg/client/auth" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/utils" ) var ( scheme = runtime.NewScheme() count int namespaces []string skipWorkload bool ) func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(webhostingv1alpha1.AddToScheme(scheme)) } func main() { cmd := &cobra.Command{ Use: "samples-generator", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { c, err := client.New(ctrl.GetConfigOrDie(), client.Options{Scheme: scheme}) if err != nil { return err } cmd.SilenceUsage = true return generateSamples(cmd.Context(), c) }, } cmd.Flags().IntVarP(&count, "count", "c", count, "number of websites to generate per project") cmd.Flags().StringSliceVarP(&namespaces, "namespace", "n", namespaces, "project namespaces to generate websites in") cmd.Flags().BoolVar(&skipWorkload, "skip-workload", false, "don't run any actual workload for the generated websites") if err := cmd.ExecuteContext(signals.SetupSignalHandler()); err != nil { fmt.Printf("Error generating samples: %v\n", err) os.Exit(1) } } func generateSamples(ctx context.Context, c client.Client) error { themeList := &webhostingv1alpha1.ThemeList{} if err := c.List(ctx, themeList); err != nil { return err } themes := make([]string, 0, len(themeList.Items)) for _, theme := range themeList.Items { themes = append(themes, theme.Name) } if len(themes) == 0 { return fmt.Errorf("no themes found, create them first") } namespaceList := &corev1.NamespaceList{} if err := c.List(ctx, namespaceList, client.MatchingLabelsSelector{Selector: webhostingv1alpha1.LabelSelectorProject}); err != nil { return err } if len(namespaceList.Items) == 0 { return fmt.Errorf("no project namespaces found, create namespaces with the %q label first", webhostingv1alpha1.LabelKeyProject) } for _, namespace := range namespaceList.Items { project := namespace.Name // nolint:gosec // doesn't need to be cryptographically secure websiteCount := rand.Intn(50) + 1 if count > 0 { websiteCount = count } for i := 0; i < websiteCount; i++ { website := &webhostingv1alpha1.Website{ ObjectMeta: metav1.ObjectMeta{ Name: "sample-" + utils.RandomName(8), Namespace: project, Labels: map[string]string{ "generated-by": "samples-generator", }, }, Spec: webhostingv1alpha1.WebsiteSpec{ Theme: utils.PickRandom(themes), }, } if skipWorkload { website.Labels[webhostingv1alpha1.LabelKeySkipWorkload] = "true" } if err := c.Create(ctx, website); err != nil { return err } } fmt.Printf("created %d Websites in project %q\n", websiteCount, project) } return nil } ================================================ FILE: webhosting-operator/cmd/webhosting-operator/main.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package main import ( "flag" "fmt" "net/http" "os" goruntime "runtime" "strconv" "go.uber.org/zap/zapcore" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" "k8s.io/klog/v2" "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/metrics/filters" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. _ "k8s.io/client-go/plugin/pkg/client/auth" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" shardlease "github.com/timebertt/kubernetes-controller-sharding/pkg/shard/lease" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/routes" configv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/config/v1alpha1" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/controllers/webhosting" webhostingmetrics "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/metrics" //+kubebuilder:scaffold:imports ) var ( scheme = runtime.NewScheme() setupLog = ctrl.Log.WithName("setup") ) func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(webhostingv1alpha1.AddToScheme(scheme)) utilruntime.Must(configv1alpha1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } func main() { ctx := ctrl.SetupSignalHandler() opts := options{} opts.AddFlags(flag.CommandLine) zapOpts := zap.Options{ TimeEncoder: zapcore.ISO8601TimeEncoder, } zapOpts.BindFlags(flag.CommandLine) flag.Parse() ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zapOpts))) klog.SetLogger(ctrl.Log) if err := opts.Complete(); err != nil { setupLog.Error(err, "unable to load config") os.Exit(1) } mgr, err := ctrl.NewManager(opts.restConfig, opts.managerOptions) if err != nil { setupLog.Error(err, "unable to start manager") os.Exit(1) } if err = (&webhosting.WebsiteReconciler{ Config: opts.config, }).SetupWithManager(mgr, opts.enableSharding, opts.controllerRingName, opts.shardName); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Website") os.Exit(1) } if err = webhostingmetrics.AddToManager(mgr); err != nil { setupLog.Error(err, "unable to add metrics exporters") os.Exit(1) } //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { setupLog.Error(err, "unable to set up health check") os.Exit(1) } if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { setupLog.Error(err, "unable to set up ready check") os.Exit(1) } setupLog.Info("starting manager") if err := mgr.Start(ctx); err != nil { setupLog.Error(err, "problem running manager") os.Exit(1) } } type options struct { configFile string restConfig *rest.Config config *configv1alpha1.WebhostingOperatorConfig managerOptions ctrl.Options enableSharding bool controllerRingName string shardName string } func (o *options) AddFlags(fs *flag.FlagSet) { fs.StringVar(&o.configFile, "config", "", "Path to the file containing the operator's configuration (WebhostingOperatorConfig). "+ "If not specified, the operator will use the default configuration values.") } func (o *options) Complete() error { o.config = &configv1alpha1.WebhostingOperatorConfig{} // load config file if specified if o.configFile != "" { configBytes, err := os.ReadFile(o.configFile) if err != nil { return fmt.Errorf("failed reading config file: %w", err) } if err := runtime.DecodeInto(serializer.NewCodecFactory(scheme).UniversalDecoder(), configBytes, o.config); err != nil { return fmt.Errorf("failed decoding config file: %w", err) } } else { scheme.Default(o.config) } // load rest config var err error o.restConfig, err = ctrl.GetConfig() if err != nil { return fmt.Errorf("failed loading kubeconfig: %w", err) } // bring everything together o.managerOptions = ctrl.Options{ Scheme: scheme, // allows us to quickly handover leadership on restarts LeaderElectionReleaseOnCancel: true, Cache: cache.Options{ DefaultTransform: dropUnwantedMetadata, }, } o.applyConfigToRESTConfig() o.applyConfigToOptions() if err := o.applyOptionsOverrides(); err != nil { return err } return nil } func (o *options) applyConfigToRESTConfig() { if clientConnection := o.config.ClientConnection; clientConnection != nil { if clientConnection.QPS > 0 { o.restConfig.QPS = clientConnection.QPS } if clientConnection.Burst > 0 { o.restConfig.Burst = int(clientConnection.Burst) } } } func (o *options) applyConfigToOptions() { if leaderElection := o.config.LeaderElection; leaderElection != nil { o.managerOptions.LeaderElection = *leaderElection.LeaderElect o.managerOptions.LeaderElectionResourceLock = leaderElection.ResourceLock o.managerOptions.LeaderElectionID = leaderElection.ResourceName o.managerOptions.LeaderElectionNamespace = leaderElection.ResourceNamespace o.managerOptions.LeaseDuration = ptr.To(leaderElection.LeaseDuration.Duration) o.managerOptions.RenewDeadline = ptr.To(leaderElection.RenewDeadline.Duration) o.managerOptions.RetryPeriod = ptr.To(leaderElection.RetryPeriod.Duration) } o.managerOptions.HealthProbeBindAddress = o.config.Health.BindAddress if o.config.Metrics.BindAddress != "0" { var extraHandlers map[string]http.Handler if *o.config.Debugging.EnableProfiling { extraHandlers = routes.ProfilingHandlers if *o.config.Debugging.EnableContentionProfiling { goruntime.SetBlockProfileRate(1) } } o.managerOptions.Metrics = metricsserver.Options{ SecureServing: true, BindAddress: o.config.Metrics.BindAddress, FilterProvider: filters.WithAuthenticationAndAuthorization, ExtraHandlers: extraHandlers, } } o.managerOptions.GracefulShutdownTimeout = ptr.To(o.config.GracefulShutdownTimeout.Duration) } func (o *options) applyOptionsOverrides() error { var err error // allow overriding leader election via env var for debugging purposes if leaderElectEnv, ok := os.LookupEnv("LEADER_ELECT"); ok { o.managerOptions.LeaderElection, err = strconv.ParseBool(leaderElectEnv) if err != nil { return fmt.Errorf("error parsing LEADER_ELECT env var: %w", err) } } // allow enabling/disabling sharding via env var for evaluation if shardingEnv, ok := os.LookupEnv("ENABLE_SHARDING"); ok { o.enableSharding, err = strconv.ParseBool(shardingEnv) if err != nil { return fmt.Errorf("error parsing ENABLE_SHARDING env var: %w", err) } } if o.enableSharding { if !o.managerOptions.LeaderElection { return fmt.Errorf("sharding cannot be enabled if leader election is disabled") } // SHARD LEASE o.controllerRingName = webhostingv1alpha1.WebhostingOperatorName shardLease, err := shardlease.NewResourceLock(o.restConfig, shardlease.Options{ ControllerRingName: o.controllerRingName, }) if err != nil { return fmt.Errorf("failed creating shard lease: %w", err) } o.shardName = shardLease.Identity() // Use manager's leader election mechanism for maintaining the shard lease. // With this, controllers will only run as long as manager holds the shard lease. // After graceful termination, the shard lease will be released. o.managerOptions.LeaderElectionResourceLockInterface = shardLease // FILTERED WATCH CACHE // Configure cache to only watch objects that are assigned to this shard. shardLabelSelector := labels.SelectorFromSet(labels.Set{ shardingv1alpha1.LabelShard(o.controllerRingName): o.shardName, }) // This operator watches sharded objects (Websites, etc.) as well as non-sharded objects (Themes), // use cache.Options.ByObject to configure the label selector on object level. o.managerOptions.Cache.ByObject = map[client.Object]cache.ByObject{ &webhostingv1alpha1.Website{}: {Label: shardLabelSelector}, &appsv1.Deployment{}: {Label: shardLabelSelector}, &corev1.ConfigMap{}: {Label: shardLabelSelector}, &corev1.Service{}: {Label: shardLabelSelector}, &networkingv1.Ingress{}: {Label: shardLabelSelector}, } } return nil } func dropUnwantedMetadata(i interface{}) (interface{}, error) { obj, ok := i.(client.Object) if !ok { return i, nil } obj.SetManagedFields(nil) annotations := obj.GetAnnotations() delete(annotations, "kubectl.kubernetes.io/last-applied-configuration") obj.SetAnnotations(annotations) return obj, nil } ================================================ FILE: webhosting-operator/config/experiment/base/job.yaml ================================================ apiVersion: batch/v1 kind: Job metadata: name: experiment spec: # don't retry this job as it might not leave behind a clean cluster -> retries will not provide meaningful results backoffLimit: 0 activeDeadlineSeconds: 1200 ttlSecondsAfterFinished: 300 template: spec: containers: - name: experiment image: experiment:latest args: - --zap-devel env: - name: RUN_ID valueFrom: fieldRef: fieldPath: metadata.uid - name: DISABLE_HTTP2 value: "true" ports: - name: metrics containerPort: 8080 protocol: TCP securityContext: allowPrivilegeEscalation: false livenessProbe: httpGet: path: /healthz port: 8081 initialDelaySeconds: 15 periodSeconds: 20 readinessProbe: httpGet: path: /readyz port: 8081 initialDelaySeconds: 5 periodSeconds: 10 resources: limits: cpu: "4" memory: 512Mi requests: cpu: "2" memory: 256Mi restartPolicy: Never securityContext: runAsNonRoot: true serviceAccountName: experiment terminationGracePeriodSeconds: 30 ================================================ FILE: webhosting-operator/config/experiment/base/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: experiment labels: - includeSelectors: true pairs: app.kubernetes.io/name: experiment images: - name: experiment newName: ghcr.io/timebertt/kubernetes-controller-sharding/experiment newTag: latest resources: - namespace.yaml - job.yaml - rbac.yaml - service.yaml # provide prometheus running in namespace "monitoring" with the permissions required for service discovery in namespace # "experiment" - prometheus_rbac.yaml - servicemonitor.yaml ================================================ FILE: webhosting-operator/config/experiment/base/namespace.yaml ================================================ apiVersion: v1 kind: Namespace metadata: name: experiment ================================================ FILE: webhosting-operator/config/experiment/base/prometheus_rbac.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus name: prometheus-k8s rules: - apiGroups: - "" resources: - services - endpoints - pods verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus name: prometheus-k8s roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: prometheus-k8s subjects: - kind: ServiceAccount name: prometheus-k8s namespace: monitoring ================================================ FILE: webhosting-operator/config/experiment/base/rbac.yaml ================================================ --- apiVersion: v1 kind: ServiceAccount metadata: name: experiment --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: experiment rules: - apiGroups: - webhosting.timebertt.dev resources: - themes - websites verbs: - get - list - watch - create - patch - update - delete - deletecollection - apiGroups: - "" resources: - namespaces verbs: - get - list - watch - create - patch - update - delete - deletecollection - apiGroups: - rbac.authorization.k8s.io resources: - clusterroles verbs: - create - delete - apiGroups: - apps resources: - deployments verbs: - get - list - watch - patch - apiGroups: - coordination.k8s.io resources: - leases verbs: - get - list - watch - deletecollection - apiGroups: - "" resources: - pods verbs: - get - list - watch - delete --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: experiment roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: experiment subjects: - kind: ServiceAccount name: experiment ================================================ FILE: webhosting-operator/config/experiment/base/service.yaml ================================================ apiVersion: v1 kind: Service metadata: name: experiment namespace: system spec: ports: - name: metrics port: 8080 protocol: TCP targetPort: metrics ================================================ FILE: webhosting-operator/config/experiment/base/servicemonitor.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: experiment spec: endpoints: - path: /metrics port: metrics scheme: http bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 10s scrapeTimeout: 10s relabelings: - targetLabel: job replacement: experiment - targetLabel: run_id sourceLabels: [__meta_kubernetes_pod_uid] selector: matchLabels: app.kubernetes.io/name: experiment ================================================ FILE: webhosting-operator/config/experiment/basic/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../base patches: - target: kind: Job name: experiment patch: | - op: add path: /spec/template/spec/containers/0/args/- value: basic ================================================ FILE: webhosting-operator/config/experiment/chaos/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../base patches: - target: kind: Job name: experiment patch: | - op: add path: /spec/template/spec/containers/0/args/- value: chaos ================================================ FILE: webhosting-operator/config/experiment/rolling-update/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../base patches: - target: kind: Job name: experiment patch: | - op: add path: /spec/template/spec/containers/0/args/- value: rolling-update ================================================ FILE: webhosting-operator/config/experiment/scale-out/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../base patches: - target: kind: Job name: experiment patch: | - op: add path: /spec/template/spec/containers/0/args/- value: scale-out ================================================ FILE: webhosting-operator/config/manager/base/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization # Adds namespace to all resources. namespace: webhosting-system # Value of this field is prepended to the # names of all resources, e.g. a deployment named # "wordpress" becomes "alices-wordpress". # Note that it should also match with the prefix (text before '-') of the namespace # field above. namePrefix: webhosting- # Labels to add to all resources and selectors. labels: - includeSelectors: true pairs: app.kubernetes.io/name: webhosting-operator images: - name: controller newName: ghcr.io/timebertt/kubernetes-controller-sharding/webhosting-operator newTag: latest resources: - namespace.yaml - manager.yaml - service.yaml - ../crds - ../rbac - metrics_auth.yaml ================================================ FILE: webhosting-operator/config/manager/base/manager.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: operator namespace: system spec: replicas: 3 template: metadata: annotations: kubectl.kubernetes.io/default-container: manager spec: automountServiceAccountToken: true securityContext: runAsNonRoot: true containers: - name: manager image: controller:latest args: [] env: - name: DISABLE_HTTP2 value: "true" - name: WEBSITE_CONCURRENT_SYNCS value: "15" ports: - name: metrics containerPort: 8080 protocol: TCP securityContext: allowPrivilegeEscalation: false livenessProbe: httpGet: path: /healthz port: 8081 initialDelaySeconds: 15 periodSeconds: 20 readinessProbe: httpGet: path: /readyz port: 8081 initialDelaySeconds: 5 periodSeconds: 10 resources: limits: cpu: "2" memory: 1Gi requests: cpu: "1" memory: 512Mi serviceAccountName: operator terminationGracePeriodSeconds: 30 ================================================ FILE: webhosting-operator/config/manager/base/metrics_auth.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: operator-metrics-auth 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: operator-metrics-auth roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: operator-metrics-auth subjects: - kind: ServiceAccount name: operator namespace: system ================================================ FILE: webhosting-operator/config/manager/base/namespace.yaml ================================================ apiVersion: v1 kind: Namespace metadata: name: system ================================================ FILE: webhosting-operator/config/manager/base/service.yaml ================================================ apiVersion: v1 kind: Service metadata: name: operator spec: type: ClusterIP ports: - port: 8080 name: metrics protocol: TCP targetPort: metrics ================================================ FILE: webhosting-operator/config/manager/controllerring/controllerring.yaml ================================================ apiVersion: sharding.timebertt.dev/v1alpha1 kind: ControllerRing metadata: name: webhosting-operator spec: resources: - group: webhosting.timebertt.dev resource: websites controlledResources: - group: apps resource: deployments - group: "" resource: configmaps - group: "" resource: services - group: networking.k8s.io resource: ingresses namespaceSelector: matchLabels: webhosting.timebertt.dev/project: "true" ================================================ FILE: webhosting-operator/config/manager/controllerring/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component resources: - controllerring.yaml - sharder_rbac.yaml patches: - path: manager_patch.yaml ================================================ FILE: webhosting-operator/config/manager/controllerring/manager_patch.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: operator namespace: system spec: template: spec: containers: - name: manager env: - name: ENABLE_SHARDING value: "true" ================================================ FILE: webhosting-operator/config/manager/controllerring/sharder_rbac.yaml ================================================ # These manifests grant the sharder controller permissions to act on resources that we listed in the ControllerRing. # We need to grant these permissions explicitly depending on what we configured. Otherwise, the sharder would require # cluster-admin access. --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: sharding:controllerring:webhosting-operator rules: - apiGroups: - webhosting.timebertt.dev resources: - websites verbs: - list - patch - apiGroups: - apps resources: - deployments verbs: - list - patch - apiGroups: - "" resources: - configmaps - services verbs: - list - patch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - list - patch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: sharding:controllerring:webhosting-operator roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: sharding:controllerring:webhosting-operator subjects: - kind: ServiceAccount name: sharder namespace: sharding-system ================================================ FILE: webhosting-operator/config/manager/crds/kustomization.yaml ================================================ # This kustomization.yaml is not intended to be run by itself, # since it depends on service name and namespace that are out of this kustomize package. # It should be run by config/manager/default resources: - webhosting.timebertt.dev_websites.yaml - webhosting.timebertt.dev_themes.yaml #+kubebuilder:scaffold:crdkustomizeresource # the following config is for teaching kustomize how to do kustomization for CRDs. configurations: - kustomizeconfig.yaml ================================================ FILE: webhosting-operator/config/manager/crds/kustomizeconfig.yaml ================================================ # This file is for teaching kustomize how to substitute name and namespace reference in CRD nameReference: - kind: Service version: v1 fieldSpecs: - kind: CustomResourceDefinition version: v1 group: apiextensions.k8s.io path: spec/conversion/webhook/clientConfig/service/name namespace: - kind: CustomResourceDefinition version: v1 group: apiextensions.k8s.io path: spec/conversion/webhook/clientConfig/service/namespace create: false varReference: - path: metadata/annotations ================================================ FILE: webhosting-operator/config/manager/crds/webhosting.timebertt.dev_themes.yaml ================================================ --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 name: themes.webhosting.timebertt.dev spec: group: webhosting.timebertt.dev names: kind: Theme listKind: ThemeList plural: themes singular: theme scope: Cluster versions: - additionalPrinterColumns: - jsonPath: .spec.color name: Color type: string - jsonPath: .spec.fontFamily name: Font Family type: string - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1alpha1 schema: openAPIV3Schema: description: Theme is the Schema for the themes 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: Spec contains the specification of the desired behavior of the Theme. properties: color: description: Color is a CSS color for a Website. type: string fontFamily: description: FontFamily is a font family for a Website. type: string required: - color - fontFamily type: object status: description: Status contains the most recently observed status of the Theme. type: object type: object served: true storage: true subresources: status: {} ================================================ FILE: webhosting-operator/config/manager/crds/webhosting.timebertt.dev_websites.yaml ================================================ --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 name: websites.webhosting.timebertt.dev spec: group: webhosting.timebertt.dev names: kind: Website listKind: WebsiteList plural: websites singular: website scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .spec.theme name: Theme type: string - jsonPath: .status.phase name: Phase type: string - jsonPath: .status.lastTransitionTime name: Since type: date - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1alpha1 schema: openAPIV3Schema: description: Website enables declarative management of hosted websites. 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 contains the specification of the desired behavior of the Website. properties: theme: description: Theme references a Theme object to be used for this Website. type: string required: - theme type: object status: description: Status contains the most recently observed status of the Website. properties: lastTransitionTime: description: LastTransitionTime is the last time the observedGeneration or phase transitioned from one value to another. format: date-time type: string observedGeneration: description: The generation observed by the Website controller. format: int64 type: integer phase: description: Phase is the current phase of this Website. type: string type: object type: object served: true storage: true subresources: status: {} ================================================ FILE: webhosting-operator/config/manager/devel/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component patches: - target: group: apps kind: Deployment name: webhosting-operator namespace: webhosting-system patch: | - op: add path: /spec/template/spec/containers/0/args/- value: --zap-devel ================================================ FILE: webhosting-operator/config/manager/overlays/debug/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base patches: - path: manager_debug_patch.yaml ================================================ FILE: webhosting-operator/config/manager/overlays/debug/manager_debug_patch.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: operator namespace: system spec: strategy: type: Recreate template: spec: securityContext: # delve can't run as non-root (when using skaffold debug) runAsNonRoot: false containers: - name: manager env: # disable leader election for debugging and use Deployment strategy Recreate. # other option would have been to increase the durations and rely on ReleaseOnCancel to release the lease, # however the delve debugger seems to kill the child process too fast for the leader elector to release the lease # (probably, this is because the network connection to the skaffold/dlv client breaks off during termination) - name: LEADER_ELECT value: "false" terminationGracePeriodSeconds: 5 ================================================ FILE: webhosting-operator/config/manager/overlays/default/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base components: - ../../controllerring ================================================ FILE: webhosting-operator/config/manager/overlays/devel/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../default components: - ../../devel ================================================ FILE: webhosting-operator/config/manager/overlays/non-sharded/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base patches: - path: manager_patch.yaml ================================================ FILE: webhosting-operator/config/manager/overlays/non-sharded/manager_patch.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: operator namespace: system spec: replicas: 1 template: spec: containers: - name: manager env: - name: ENABLE_SHARDING value: "false" # When comparing singleton vs sharded setups, the singleton will fail to verify the SLOs because it has too few # website workers. Increase the worker count to allow comparing the setups. - name: WEBSITE_CONCURRENT_SYNCS value: "50" ================================================ FILE: webhosting-operator/config/manager/overlays/non-sharded-devel/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../non-sharded components: - ../../devel ================================================ FILE: webhosting-operator/config/manager/overlays/shoot/default/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../default components: - ../../../with-dns ================================================ FILE: webhosting-operator/config/manager/overlays/shoot/devel/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../default components: - ../../../devel ================================================ FILE: webhosting-operator/config/manager/overlays/shoot/non-sharded/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../non-sharded components: - ../../../with-dns ================================================ FILE: webhosting-operator/config/manager/overlays/shoot/non-sharded-devel/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../non-sharded components: - ../../../devel ================================================ FILE: webhosting-operator/config/manager/rbac/kustomization.yaml ================================================ resources: # All RBAC will be applied under this service account in # the deployment namespace. You may comment out this resource # if your manager will use a service account that exists at # runtime. Be sure to update RoleBinding and ClusterRoleBinding # subjects if changing service account names. - service_account.yaml - role.yaml - role_binding.yaml - leader_election_role.yaml - leader_election_role_binding.yaml # provide parca running in namespace "parca" with the permissions required for service discovery in namespace # "webhosting-system" and scrape the pprof endpoints of webhosting-operator - parca_rbac.yaml ================================================ FILE: webhosting-operator/config/manager/rbac/leader_election_role.yaml ================================================ # permissions to do leader election. apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: leader-election rules: - apiGroups: - coordination.k8s.io resources: - leases verbs: - get - list - watch - create - update - patch - delete - apiGroups: - "" resources: - events verbs: - create - patch ================================================ FILE: webhosting-operator/config/manager/rbac/leader_election_role_binding.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: leader-election roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: leader-election subjects: - kind: ServiceAccount name: operator namespace: system ================================================ FILE: webhosting-operator/config/manager/rbac/parca_rbac.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: parca-service-discovery rules: - apiGroups: - "" resources: - services - endpoints - pods verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: parca-service-discovery roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: parca-service-discovery subjects: - kind: ServiceAccount name: parca namespace: parca --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: operator-pprof-reader rules: - nonResourceURLs: - "/debug/pprof/allocs" - "/debug/pprof/block" - "/debug/pprof/goroutine" - "/debug/pprof/heap" - "/debug/pprof/mutex" - "/debug/pprof/profile" - "/debug/pprof/symbol" - "/debug/pprof/threadcreate" - "/debug/pprof/trace" verbs: - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: observability app.kubernetes.io/instance: parca app.kubernetes.io/name: parca name: parca-pprof-reader roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: operator-pprof-reader subjects: - kind: ServiceAccount name: parca namespace: parca ================================================ FILE: webhosting-operator/config/manager/rbac/role.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: operator rules: - apiGroups: - "" resources: - configmaps - services verbs: - create - get - list - patch - watch - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - apps resources: - deployments verbs: - create - get - list - patch - watch - apiGroups: - coordination.k8s.io resources: - leases verbs: - delete - get - list - patch - update - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - create - get - list - patch - watch - apiGroups: - webhosting.timebertt.dev resources: - themes verbs: - get - list - watch - apiGroups: - webhosting.timebertt.dev resources: - websites verbs: - create - delete - get - list - patch - update - watch - apiGroups: - webhosting.timebertt.dev resources: - websites/finalizers verbs: - update - apiGroups: - webhosting.timebertt.dev resources: - websites/status verbs: - get - patch - update ================================================ FILE: webhosting-operator/config/manager/rbac/role_binding.yaml ================================================ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: operator roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: operator subjects: - kind: ServiceAccount name: operator namespace: system ================================================ FILE: webhosting-operator/config/manager/rbac/service_account.yaml ================================================ apiVersion: v1 kind: ServiceAccount metadata: name: operator namespace: system automountServiceAccountToken: false ================================================ FILE: webhosting-operator/config/manager/rbac/theme_editor_role.yaml ================================================ # permissions for end users to edit themes. apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: theme-editor-role rules: - apiGroups: - webhosting.timebertt.dev resources: - themes verbs: - create - delete - get - list - patch - update - watch - apiGroups: - webhosting.timebertt.dev resources: - themes/status verbs: - get ================================================ FILE: webhosting-operator/config/manager/rbac/theme_viewer_role.yaml ================================================ # permissions for end users to view themes. apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: theme-viewer-role rules: - apiGroups: - webhosting.timebertt.dev resources: - themes verbs: - get - list - watch - apiGroups: - webhosting.timebertt.dev resources: - themes/status verbs: - get ================================================ FILE: webhosting-operator/config/manager/rbac/website_editor_role.yaml ================================================ # permissions for end users to edit websites. apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: website-editor-role rules: - apiGroups: - webhosting.timebertt.dev resources: - websites verbs: - create - delete - get - list - patch - update - watch - apiGroups: - webhosting.timebertt.dev resources: - websites/status verbs: - get ================================================ FILE: webhosting-operator/config/manager/rbac/website_viewer_role.yaml ================================================ # permissions for end users to view websites. apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: website-viewer-role rules: - apiGroups: - webhosting.timebertt.dev resources: - websites verbs: - get - list - watch - apiGroups: - webhosting.timebertt.dev resources: - websites/status verbs: - get ================================================ FILE: webhosting-operator/config/manager/with-dns/config.yaml ================================================ apiVersion: config.webhosting.timebertt.dev/v1alpha1 kind: WebhostingOperatorConfig ingress: hosts: - webhosting.timebertt.dev tls: - hosts: - webhosting.timebertt.dev ================================================ FILE: webhosting-operator/config/manager/with-dns/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component generatorOptions: disableNameSuffixHash: true configMapGenerator: - name: webhosting-operator namespace: webhosting-system files: - config.yaml patches: - path: manager_patch.yaml - target: group: apps kind: Deployment name: webhosting-operator namespace: webhosting-system patch: | - op: add path: /spec/template/spec/containers/0/args/- value: --config=/config.yaml ================================================ FILE: webhosting-operator/config/manager/with-dns/manager_patch.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: webhosting-operator namespace: webhosting-system spec: template: spec: containers: - name: manager volumeMounts: - name: config mountPath: /config.yaml subPath: config.yaml volumes: - name: config configMap: name: webhosting-operator ================================================ FILE: webhosting-operator/config/monitoring/default/dashboards/experiments.json ================================================ { "annotations": { "list": [ { "builtIn": 1, "datasource": { "type": "grafana", "uid": "-- Grafana --" }, "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" } ] }, "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 1, "id": 35, "links": [], "panels": [ { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 1, "panels": [], "title": "Controller Load", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic", "seriesBy": "last" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "axisSoftMax": 10000, "axisSoftMin": 0, "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "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": "short" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 1 }, "id": 2, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "single", "sort": "none" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "editorMode": "code", "expr": "sum(namespace_run:kube_website_info:sum{run_id=~\"$run_id\"}) by (run_id)", "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "Website Count", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 1 }, "id": 3, "options": { "legend": { "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true, "sortBy": "Last *", "sortDesc": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "editorMode": "code", "expr": "sum(\n rate(controller_runtime_reconcile_total{\n job=\"experiment\", run_id=~\"$run_id\",\n controller=~\"website-(generator|deleter|mutator)\",\n result!=\"error\",\n }[$__rate_interval])\n) by (controller)", "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "Website Churn", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 9 }, "id": 4, "panels": [], "title": "Controller SLOs", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "description": "", "fieldConfig": { "defaults": { "color": { "fixedColor": "text", "mode": "palette-classic", "seriesBy": "last" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "dashed+area" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 1 } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 10 }, "id": 5, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true, "sortBy": "Last *", "sortDesc": true }, "tooltip": { "hideZeros": false, "mode": "single", "sort": "desc" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "editorMode": "code", "expr": "histogram_quantile($percentile/100,\n sum by (run_id, le) (rate(\n workqueue_queue_duration_seconds_bucket{\n job=\"webhosting-operator\", name=\"website\", run_id=~\"$run_id\"\n }[1m]\n ))\n)", "legendFormat": "{{run_id}}-1m", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "editorMode": "code", "expr": "histogram_quantile($percentile/100,\n sum by (run_id, le) (rate(\n workqueue_queue_duration_seconds_bucket{\n job=\"webhosting-operator\", name=\"website\", run_id=~\"$run_id\"\n }[15m]\n ))\n)", "hide": false, "legendFormat": "{{run_id}}-15m", "range": true, "refId": "B" } ], "title": "Queue Latency (P$percentile)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "description": "", "fieldConfig": { "defaults": { "color": { "fixedColor": "text", "mode": "palette-classic", "seriesBy": "last" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "log": 2, "type": "log" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "dashed+area" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 5 } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 10 }, "id": 6, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true, "sortBy": "Last *", "sortDesc": true }, "tooltip": { "hideZeros": false, "mode": "single", "sort": "desc" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "editorMode": "code", "expr": "histogram_quantile($percentile/100,\n sum by (run_id, le) (rate(\n experiment_website_reconciliation_duration_seconds_bucket{\n job=\"experiment\", run_id=~\"$run_id\"\n }[1m]\n ))\n)", "legendFormat": "{{run_id}}-1m", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "editorMode": "code", "expr": "histogram_quantile($percentile/100,\n sum by (run_id, le) (rate(\n experiment_website_reconciliation_duration_seconds_bucket{\n job=\"experiment\", run_id=~\"$run_id\"\n }[15m]\n ))\n)", "hide": false, "legendFormat": "{{run_id}}-15m", "range": true, "refId": "B" } ], "title": "Reconciliation Latency (P$percentile)", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 18 }, "id": 7, "panels": [], "title": "Controller Resource Usage", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "description": "", "fieldConfig": { "defaults": { "color": { "fixedColor": "text", "mode": "palette-classic", "seriesBy": "last" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "axisSoftMin": 0, "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" } ] }, "unit": "cores" }, "overrides": [] }, "gridPos": { "h": 8, "w": 24, "x": 0, "y": 19 }, "id": 8, "options": { "legend": { "calcs": [ "max" ], "displayMode": "table", "placement": "right", "showLegend": true, "sortBy": "Last *", "sortDesc": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "editorMode": "code", "expr": "sum by (namespace, pod) (rate(\n container_cpu_usage_seconds_total{\n pod=~\"sharder-.+|webhosting-operator-.+\",\n container=~\"sharder|manager\"\n }[1m]\n)) * on (namespace, pod) group_left (run_id) max by (namespace, pod, run_id) (kube_pod_labels{run_id=~\"$run_id\"})", "legendFormat": "{{pod}}", "range": true, "refId": "A" } ], "title": "CPU Usage by pod", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "description": "", "fieldConfig": { "defaults": { "color": { "fixedColor": "text", "mode": "palette-classic", "seriesBy": "last" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "axisSoftMin": 0, "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" } ] }, "unit": "bytes" }, "overrides": [] }, "gridPos": { "h": 8, "w": 24, "x": 0, "y": 27 }, "id": 9, "options": { "legend": { "calcs": [ "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "editorMode": "code", "expr": "sum by (namespace, pod, run_id) (\n go_memory_classes_total_bytes{pod=~\"sharder-.+|webhosting-operator-.+\",run_id=~\"$run_id\"}\n - go_memory_classes_heap_released_bytes{\n pod=~\"sharder-.+|webhosting-operator-.+\",\n run_id=~\"$run_id\"\n }\n - go_memory_classes_heap_unused_bytes{\n pod=~\"sharder-.+|webhosting-operator-.+\",\n run_id=~\"$run_id\"\n }\n - go_memory_classes_heap_free_bytes{\n pod=~\"sharder-.+|webhosting-operator-.+\",\n run_id=~\"$run_id\"\n }\n)", "legendFormat": "{{pod}}", "range": true, "refId": "A" } ], "title": "Memory Usage by pod", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "description": "", "fieldConfig": { "defaults": { "color": { "fixedColor": "text", "mode": "palette-classic", "seriesBy": "last" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "axisSoftMin": 0, "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" } ] }, "unit": "binBps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 24, "x": 0, "y": 35 }, "id": 10, "options": { "legend": { "calcs": [ "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "editorMode": "code", "expr": "sum by (namespace, pod, run_id) (rate(\n container_network_receive_bytes_total{\n pod=~\"sharder-.+|webhosting-operator-.+\"\n }[1m]\n)) * on (namespace, pod) group_left (run_id) max by (namespace, pod, run_id) (kube_pod_labels{run_id=~\"$run_id\"})", "legendFormat": "{{pod}}", "range": true, "refId": "A" } ], "title": "Network Receive by pod", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "description": "", "fieldConfig": { "defaults": { "color": { "fixedColor": "text", "mode": "palette-classic", "seriesBy": "last" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "axisSoftMin": 0, "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 50, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" } ] }, "unit": "binBps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 24, "x": 0, "y": 43 }, "id": 11, "options": { "legend": { "calcs": [ "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "editorMode": "code", "expr": "sum by (namespace, pod, run_id) (rate(\n container_network_transmit_bytes_total{\n pod=~\"sharder-.+|webhosting-operator-.+\"\n }[1m]\n)) * on (namespace, pod) group_left (run_id) max by (namespace, pod, run_id) (kube_pod_labels{run_id=~\"$run_id\"})", "legendFormat": "{{pod}}", "range": true, "refId": "A" } ], "title": "Network Transmit by pod", "type": "timeseries" } ], "preload": false, "refresh": "10s", "schemaVersion": 41, "tags": [], "templating": { "list": [ { "allValue": ".*", "current": { "text": [ "All" ], "value": [ "$__all" ] }, "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "definition": "label_values(up{job=\"experiment\"},run_id)", "includeAll": true, "multi": true, "name": "run_id", "options": [], "query": { "qryType": 1, "query": "label_values(up{job=\"experiment\"},run_id)", "refId": "PrometheusVariableQueryEditor-VariableQuery" }, "refresh": 2, "regex": "", "sort": 1, "type": "query" }, { "current": { "text": "99", "value": "99" }, "label": "SLO Percentile", "name": "percentile", "options": [ { "selected": false, "text": "90", "value": "90" }, { "selected": false, "text": "95", "value": "95" }, { "selected": true, "text": "99", "value": "99" } ], "query": "90,95,99", "type": "custom" } ] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": {}, "timezone": "", "title": "Experiments", "uid": "d33509b4-7e28-41e2-961a-4d7fbad57d01", "version": 2 } ================================================ FILE: webhosting-operator/config/monitoring/default/dashboards/sharding.json ================================================ { "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": 5, "links": [], "panels": [ { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 6, "panels": [], "title": "Headlines", "type": "row" }, { "datasource": { "default": false, "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "max": 10, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "gridPos": { "h": 6, "w": 3, "x": 0, "y": 1 }, "id": 9, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showPercentChange": false, "textMode": "auto", "wideLayout": true }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "expr": "max(max(controller_sharding_controllerring_status_available_shards{controllerring=\"$controllerring\"}) by(controllerring)) or vector(0)", "hide": false, "range": true, "refId": "A" } ], "title": "Available Shards", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "max": 10, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "gridPos": { "h": 6, "w": 3, "x": 3, "y": 1 }, "id": 21, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showPercentChange": false, "textMode": "auto", "wideLayout": true }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "expr": "max(max(controller_sharding_controllerring_status_shards{controllerring=\"$controllerring\"}) by(controllerring)) or vector(0)", "range": true, "refId": "A" } ], "title": "Total Shards", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineStyle": { "fill": "solid" }, "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" }, { "color": "red", "value": 80 } ] } }, "overrides": [ { "matcher": { "id": "byName", "options": "dead" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "orphaned" }, "properties": [ { "id": "color", "value": { "fixedColor": "#9f9f9f", "mode": "fixed", "seriesBy": "last" } } ] }, { "matcher": { "id": "byName", "options": "uncertain" }, "properties": [ { "id": "color", "value": { "fixedColor": "#ffffff", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "unknown" }, "properties": [ { "id": "color", "value": { "fixedColor": "purple", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "expired" }, "properties": [ { "id": "color", "value": { "fixedColor": "yellow", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "ready" }, "properties": [ { "id": "color", "value": { "fixedColor": "green", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 6, "w": 8, "x": 6, "y": 1 }, "id": 12, "options": { "legend": { "calcs": [ "last" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(max(controller_sharding_shard_state{controllerring=\"$controllerring\"}) without(instance, pod)) by (state)", "hide": false, "instant": false, "interval": "", "legendFormat": "{{shard}}", "range": true, "refId": "A" } ], "title": "Shards per State", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "max": 100, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "red" }, { "color": "orange", "value": 70 }, { "color": "yellow", "value": 80 }, { "color": "green", "value": 95 } ] }, "unit": "percent" }, "overrides": [] }, "gridPos": { "h": 6, "w": 5, "x": 14, "y": 1 }, "id": 10, "options": { "minVizHeight": 75, "minVizWidth": 75, "orientation": "auto", "reduceOptions": { "calcs": [ "last" ], "fields": "", "values": false }, "showThresholdLabels": false, "showThresholdMarkers": true, "sizing": "auto" }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "(max(max(controller_sharding_controllerring_status_available_shards{controllerring=\"$controllerring\"}) by(controllerring)) or vector(0)) / (max(max(controller_sharding_controllerring_status_shards{controllerring=\"$controllerring\"}) by(controllerring)) or vector(0)) * 100", "instant": true, "range": false, "refId": "A" } ], "title": "Shard Readiness", "type": "gauge" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "color": { "fixedColor": "green", "mode": "palette-classic" }, "custom": { "hideFrom": { "legend": false, "tooltip": false, "viz": false } }, "mappings": [], "max": 100, "min": 0, "unit": "percentunit" }, "overrides": [] }, "gridPos": { "h": 6, "w": 5, "x": 19, "y": 1 }, "id": 16, "options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": false }, "pieType": "pie", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "tooltip": { "hideZeros": false, "mode": "single", "sort": "none" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(namespace_shard:kube_website_shard:sum{namespace=~\"$project\",shard!=\"\"} or 0*max(controller_sharding_shard_info{controllerring=\"$controllerring\"}) by (shard)) by (shard) / ignoring(shard) group_left sum(namespace_shard:kube_website_shard:sum{namespace=~\"$project\"}) or vector(0)", "instant": true, "legendFormat": "__auto", "range": false, "refId": "A" } ], "title": "Object Distribution", "type": "piechart" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 7 }, "id": 2, "panels": [], "title": "Object Distribution", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineStyle": { "fill": "solid" }, "lineWidth": 1, "pointSize": 4, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": true, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 11, "w": 12, "x": 0, "y": 8 }, "id": 8, "options": { "legend": { "calcs": [ "max", "last" ], "displayMode": "table", "placement": "bottom", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(namespace_shard:kube_website_shard:sum{namespace=~\"$project\",shard!=\"\"} or 0*max(controller_sharding_shard_info{controllerring=\"$controllerring\"}) by (shard)) by (shard)", "instant": false, "interval": "", "legendFormat": "{{shard}}", "range": true, "refId": "A" } ], "title": "Websites Count per Shard", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": true, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "decimals": 0, "mappings": [], "max": 1, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 80 } ] }, "unit": "percentunit" }, "overrides": [] }, "gridPos": { "h": 11, "w": 12, "x": 12, "y": 8 }, "id": 11, "options": { "legend": { "calcs": [ "mean", "last" ], "displayMode": "table", "placement": "bottom", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(namespace_shard:kube_website_shard:sum{namespace=~\"$project\",shard!=\"\"} or 0*max(controller_sharding_shard_info{controllerring=\"$controllerring\"}) by (shard)) by (shard) / ignoring(shard) group_left sum(namespace_shard:kube_website_shard:sum{namespace=~\"$project\"})", "format": "time_series", "instant": false, "interval": "", "legendFormat": "{{shard}}", "range": true, "refId": "A" } ], "title": "Websites Percentage per Shard", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineStyle": { "fill": "solid" }, "lineWidth": 1, "pointSize": 4, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": true, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "Unassigned" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Draining" }, "properties": [ { "id": "color", "value": { "fixedColor": "yellow", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Assigned" }, "properties": [ { "id": "color", "value": { "fixedColor": "green", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Assigned to unready" }, "properties": [ { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 19 }, "id": 15, "options": { "legend": { "calcs": [ "max", "last" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(namespace_shard_drain:kube_website_shard:sum{namespace=~\"$project\",shard!=\"\",drain=\"\"} * on(shard) group_left max(controller_sharding_shard_state{controllerring=\"$controllerring\",state=\"ready\"}) without(instance,pod)) or vector(0)", "instant": false, "interval": "", "legendFormat": "Assigned", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(namespace_shard_drain:kube_website_shard:sum{namespace=~\"$project\",shard!=\"\",drain=\"\"} * on(shard) group_left max(kube_shard_state{controllerring=\"$controllerring\",state!=\"ready\"}) by (shard)) or vector(0)", "hide": false, "instant": false, "interval": "", "legendFormat": "Assigned to unready", "range": true, "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(namespace_shard_drain:kube_website_shard:sum{namespace=~\"$project\",drain!=\"\"}) or vector(0)", "hide": false, "instant": false, "interval": "", "legendFormat": "Draining", "range": true, "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "sum(namespace_shard_drain:kube_website_shard:sum{namespace=~\"$project\",shard=\"\"}) or vector(0)", "hide": false, "instant": false, "interval": "", "legendFormat": "Unassigned", "range": true, "refId": "D" } ], "title": "Websites Count per Sharding State", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 27 }, "id": 18, "panels": [], "title": "Sharder", "type": "row" }, { "datasource": { "default": false, "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 100, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineStyle": { "fill": "solid" }, "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": "ops" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 28 }, "id": 14, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "single", "sort": "none" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(controller_sharding_assignments_total{controllerring=\"$controllerring\", group=~\"$group\", resource=~\"$resource\"}[$__rate_interval])) or vector(0)", "hide": false, "interval": "", "legendFormat": "Assignments", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(controller_sharding_movements_total{controllerring=\"$controllerring\", group=~\"$group\", resource=~\"$resource\"}[$__rate_interval])) or vector(0)", "hide": false, "interval": "", "legendFormat": "Movements", "range": true, "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(controller_sharding_drains_total{controllerring=\"$controllerring\", group=~\"$group\", resource=~\"$resource\"}[$__rate_interval])) or vector(0)", "hide": false, "interval": "", "legendFormat": "Drains", "range": true, "refId": "C" } ], "title": "Sharder Actions", "type": "timeseries" }, { "datasource": { "default": false, "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 100, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineStyle": { "fill": "solid" }, "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": "ops" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 28 }, "id": 19, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "right", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(controller_sharding_assignments_total{controllerring=\"$controllerring\", group=~\"$group\", resource=~\"$resource\"}[$__rate_interval])) by (resource)", "hide": false, "interval": "", "legendFormat": "{{kind}}", "range": true, "refId": "A" } ], "title": "Sharder Assignments by resource", "type": "timeseries" }, { "datasource": { "default": false, "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 100, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineStyle": { "fill": "solid" }, "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": "reqps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 36 }, "id": 22, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "single", "sort": "none" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(controller_runtime_webhook_requests_total{job=\"sharder\", webhook=\"/webhooks/sharder/\"}[$__rate_interval])) by (code)", "hide": false, "interval": "", "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "Sharder Webhook Requests by code", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 100, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineStyle": { "fill": "solid" }, "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": "s" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 36 }, "id": 23, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "single", "sort": "none" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "histogram_quantile(0.9, sum(rate(controller_runtime_webhook_latency_seconds_bucket{job=\"sharder\", webhook=\"/webhooks/sharder/\"}[$__rate_interval])) by (le))", "hide": false, "interval": "", "legendFormat": "P90", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "histogram_quantile(0.95, sum(rate(controller_runtime_webhook_latency_seconds_bucket{job=\"sharder\", webhook=\"/webhooks/sharder/\"}[$__rate_interval])) by (le))", "hide": false, "interval": "", "legendFormat": "P95", "range": true, "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "histogram_quantile(0.99, sum(rate(controller_runtime_webhook_latency_seconds_bucket{job=\"sharder\", webhook=\"/webhooks/sharder/\"}[$__rate_interval])) by (le))", "hide": false, "interval": "", "legendFormat": "P99", "range": true, "refId": "C" } ], "title": "Sharder Webhook Latency", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 100, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineStyle": { "fill": "solid" }, "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": "ops" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 44 }, "id": 20, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "right", "showLegend": false }, "tooltip": { "hideZeros": false, "mode": "single", "sort": "none" } }, "pluginVersion": "12.0.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(rate(controller_sharding_ring_calculations_total{controllerring=\"$controllerring\"}[$__rate_interval]))", "hide": false, "interval": "", "legendFormat": "Ring Calculations", "range": true, "refId": "A" } ], "title": "Sharder Ring Calculations", "type": "timeseries" } ], "preload": false, "refresh": "10s", "schemaVersion": 41, "tags": [ "webhosting-operator" ], "templating": { "list": [ { "current": { "text": "prometheus", "value": "P1809F7CD0C75ACF3" }, "includeAll": false, "name": "datasource", "options": [], "query": "prometheus", "refresh": 1, "regex": "", "type": "datasource" }, { "allValue": ".*", "current": { "text": "webhosting-operator", "value": "webhosting-operator" }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(controller_sharding_controllerring_metadata_generation,controllerring)", "includeAll": false, "name": "controllerring", "options": [], "query": { "qryType": 1, "query": "label_values(controller_sharding_controllerring_metadata_generation,controllerring)", "refId": "PrometheusVariableQueryEditor-VariableQuery" }, "refresh": 2, "regex": "", "sort": 1, "type": "query" }, { "allValue": ".*", "current": { "text": [ "All" ], "value": [ "$__all" ] }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(controller_sharding_assignments_total{controllerring=\"$controllerring\"},group)", "includeAll": true, "multi": true, "name": "group", "options": [], "query": { "qryType": 1, "query": "label_values(controller_sharding_assignments_total{controllerring=\"$controllerring\"},group)", "refId": "PrometheusVariableQueryEditor-VariableQuery" }, "refresh": 2, "regex": "", "sort": 1, "type": "query" }, { "allValue": ".*", "current": { "text": [ "All" ], "value": [ "$__all" ] }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(controller_sharding_assignments_total{controllerring=\"$controllerring\", group=~\"$group\"},resource)", "includeAll": true, "multi": true, "name": "resource", "options": [], "query": { "qryType": 1, "query": "label_values(controller_sharding_assignments_total{controllerring=\"$controllerring\", group=~\"$group\"},resource)", "refId": "PrometheusVariableQueryEditor-VariableQuery" }, "refresh": 2, "regex": "", "sort": 1, "type": "query" }, { "allValue": ".*", "current": { "text": [ "All" ], "value": [ "$__all" ] }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(kube_namespace_status_phase{job=\"kube-state-metrics\", namespace=~\"project-.+\"},namespace)", "includeAll": true, "multi": true, "name": "project", "options": [], "query": { "query": "label_values(kube_namespace_status_phase{job=\"kube-state-metrics\", namespace=~\"project-.+\"}, namespace)", "refId": "StandardVariableQuery" }, "refresh": 2, "regex": "", "sort": 1, "type": "query" } ] }, "time": { "from": "now-30m", "to": "now" }, "timepicker": {}, "timezone": "", "title": "Sharding", "uid": "7liIybkVk", "version": 1 } ================================================ FILE: webhosting-operator/config/monitoring/default/dashboards/webhosting.json ================================================ { "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 over Webhosting objects", "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 1, "links": [], "liveNow": true, "panels": [ { "collapsed": false, "datasource": { "type": "datasource", "uid": "grafana" }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 6, "panels": [], "title": "Headlines", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] } }, "overrides": [] }, "gridPos": { "h": 5, "w": 8, "x": 0, "y": 1 }, "id": 2, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "pluginVersion": "9.5.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(namespace_run:kube_website_info:sum{namespace=~\"$project\"}) or vector(0)", "interval": "", "legendFormat": "", "range": true, "refId": "A" } ], "title": "Websites", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "max": 100, "min": 0, "thresholds": { "mode": "percentage", "steps": [ { "color": "red", "value": null }, { "color": "orange", "value": 80 }, { "color": "yellow", "value": 90 }, { "color": "green", "value": 98 } ] }, "unit": "percent" }, "overrides": [] }, "gridPos": { "h": 5, "w": 6, "x": 8, "y": 1 }, "id": 12, "options": { "orientation": "auto", "reduceOptions": { "calcs": [ "last" ], "fields": "", "values": false }, "showThresholdLabels": false, "showThresholdMarkers": true }, "pluginVersion": "9.5.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": false, "expr": "(sum(namespace_phase:kube_website_status_phase:sum{namespace=~\"$project\",phase=\"Ready\"}) or vector(0)) / (sum(namespace_phase:kube_website_status_phase:sum{namespace=~\"$project\"}) or vector(0)) * 100", "instant": true, "interval": "", "legendFormat": "", "range": false, "refId": "A" } ], "title": "Website Readiness", "type": "gauge" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "gridPos": { "h": 5, "w": 5, "x": 14, "y": 1 }, "id": 8, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "pluginVersion": "9.5.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(max(kube_theme_info) without (instance, pod)) or vector(0)", "interval": "", "legendFormat": "", "range": true, "refId": "A" } ], "title": "Themes", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "gridPos": { "h": 5, "w": 5, "x": 19, "y": 1 }, "id": 7, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "pluginVersion": "9.5.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(kube_namespace_status_phase{namespace=~\"project-.+\"}) or vector(0)", "interval": "", "legendFormat": "", "range": true, "refId": "A" } ], "title": "Projects", "type": "stat" }, { "collapsed": false, "datasource": { "type": "datasource", "uid": "grafana" }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 6 }, "id": 4, "panels": [], "title": "Details", "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": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineStyle": { "fill": "solid" }, "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "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 } ] } }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 7 }, "id": 10, "options": { "legend": { "calcs": [ "last" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(namespace_run:kube_website_info:sum{namespace=~\"$project\"} or 0*sum(kube_namespace_status_phase{namespace=~\"$project\"}) by (namespace)) by (namespace)", "interval": "", "legendFormat": "{{namespace}}", "range": true, "refId": "A" } ], "title": "Websites per Project", "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": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineStyle": { "fill": "solid" }, "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "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 } ] } }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 7 }, "id": 13, "options": { "legend": { "calcs": [ "last" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(sum(namespace_theme:kube_website_info:sum{namespace=~\"$project\"}) by (theme) or 0*max(kube_theme_info{}) by (theme)) by (theme)", "interval": "", "legendFormat": "{{namespace}}", "range": true, "refId": "A" } ], "title": "Websites per Theme", "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": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "smooth", "lineStyle": { "fill": "solid" }, "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] } }, "overrides": [ { "matcher": { "id": "byName", "options": "Error" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Ready" }, "properties": [ { "id": "color", "value": { "fixedColor": "green", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Pending" }, "properties": [ { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Terminating" }, "properties": [ { "id": "color", "value": { "fixedColor": "yellow", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 15 }, "id": 14, "options": { "legend": { "calcs": [ "last" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${datasource}" }, "editorMode": "code", "exemplar": true, "expr": "sum(namespace_phase:kube_website_status_phase:sum{namespace=~\"$project\"}) by (phase)", "interval": "", "legendFormat": "{{phase}}", "range": true, "refId": "A" } ], "title": "Websites per Phase", "type": "timeseries" }, { "collapsed": false, "datasource": { "type": "datasource", "uid": "grafana" }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 23 }, "id": 18, "panels": [], "title": "Websites", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "custom": { "align": "auto", "cellOptions": { "type": "auto" }, "inspect": false }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] } }, "overrides": [ { "matcher": { "id": "byName", "options": "website" }, "properties": [ { "id": "links", "value": [ { "targetBlank": true, "title": "Open Website", "url": "https://webhosting.timebertt.dev/${__data.fields.namespace}/${__data.fields.website}" } ] } ] }, { "matcher": { "id": "byName", "options": "Value" }, "properties": [ { "id": "custom.hidden", "value": true } ] } ] }, "gridPos": { "h": 12, "w": 24, "x": 0, "y": 24 }, "id": 19, "options": { "cellHeight": "sm", "footer": { "countRows": false, "fields": "", "reducer": [ "sum" ], "show": false }, "showHeader": true }, "pluginVersion": "9.5.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "P1809F7CD0C75ACF3" }, "editorMode": "code", "exemplar": true, "expr": "sum(kube_website_info{namespace=~\"$project\", website!~\"experiment-.+\"} * on(theme) group_left(color, font_family) max(kube_theme_info) without (instance, pod)) by (namespace, theme, website, color, font_family)", "format": "table", "instant": true, "interval": "", "legendFormat": "", "refId": "A" } ], "title": "Website List", "transformations": [ { "id": "organize", "options": { "excludeByName": { "Time": true, "Value #A": true }, "indexByName": { "Time": 0, "Value #A": 6, "color": 4, "font_family": 5, "namespace": 1, "theme": 3, "website": 2 }, "renameByName": {} } } ], "type": "table" } ], "refresh": "10s", "schemaVersion": 38, "style": "dark", "tags": [ "webhosting-operator" ], "templating": { "list": [ { "current": { "selected": false, "text": "prometheus", "value": "prometheus" }, "hide": 0, "includeAll": false, "multi": false, "name": "datasource", "options": [], "query": "prometheus", "refresh": 1, "regex": "", "skipUrlSync": false, "type": "datasource" }, { "allValue": "project-.+", "current": { "selected": true, "text": [ "All" ], "value": [ "$__all" ] }, "datasource": { "type": "prometheus", "uid": "${datasource}" }, "definition": "label_values(kube_namespace_status_phase{job=\"kube-state-metrics\", namespace=~\"project-.+\"}, namespace)", "hide": 0, "includeAll": true, "multi": true, "name": "project", "options": [], "query": { "query": "label_values(kube_namespace_status_phase{job=\"kube-state-metrics\", namespace=~\"project-.+\"}, namespace)", "refId": "StandardVariableQuery" }, "refresh": 2, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": {}, "timezone": "", "title": "Webhosting", "uid": "NbmNpqEnk", "version": 1, "weekStart": "" } ================================================ FILE: webhosting-operator/config/monitoring/default/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../webhosting-operator generatorOptions: disableNameSuffixHash: true configMapGenerator: - files: - dashboards/sharding.json - dashboards/webhosting.json - dashboards/experiments.json name: grafana-dashboards-sharding namespace: monitoring options: labels: grafana_dashboard: "true" ================================================ FILE: webhosting-operator/config/monitoring/webhosting-operator/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: webhosting-system labels: - includeSelectors: true pairs: app.kubernetes.io/name: webhosting-operator resources: # provide prometheus running in namespace "monitoring" with the permissions required for service discovery in namespace # "webhosting-system" - prometheus_rbac.yaml - servicemonitor.yaml - prometheusrule.yaml ================================================ FILE: webhosting-operator/config/monitoring/webhosting-operator/prometheus_rbac.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus name: prometheus-k8s rules: - apiGroups: - "" resources: - services - endpoints - pods verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus name: prometheus-k8s roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: prometheus-k8s subjects: - kind: ServiceAccount name: prometheus-k8s namespace: monitoring ================================================ FILE: webhosting-operator/config/monitoring/webhosting-operator/prometheusrule.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: webhosting-operator spec: groups: - name: webhosting-website.rules rules: - record: namespace_run:kube_website_info:sum expr: sum by (namespace, run_id) (kube_website_info) - record: namespace_theme:kube_website_info:sum expr: sum by (namespace, theme) (kube_website_info) - record: namespace_phase:kube_website_status_phase:sum expr: sum by (namespace, phase) (kube_website_status_phase) - record: namespace_shard:kube_website_shard:sum expr: sum by (namespace, shard) (kube_website_shard) - record: namespace_shard_drain:kube_website_shard:sum expr: sum by (namespace, shard, drain) (kube_website_shard) ================================================ FILE: webhosting-operator/config/monitoring/webhosting-operator/servicemonitor.yaml ================================================ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: webhosting-operator spec: endpoints: - path: /metrics port: metrics scheme: https bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token honorLabels: true interval: 10s scrapeTimeout: 10s tlsConfig: insecureSkipVerify: true relabelings: - action: labelmap regex: "__meta_kubernetes_pod_label_label_prometheus_io_(.*)" replacement: "${1}" jobLabel: app.kubernetes.io/name selector: matchLabels: app.kubernetes.io/name: webhosting-operator ================================================ FILE: webhosting-operator/config/policy/experiment-scheduling.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: experiment-scheduling spec: failurePolicy: Fail rules: # schedule experiment on dedicated worker pool for better isolation in load tests - name: add-scheduling-constraints match: any: - resources: kinds: - Pod namespaces: - experiment selector: matchLabels: app.kubernetes.io/name: experiment operations: - CREATE mutate: patchesJson6902: |- - op: add path: "/spec/tolerations/-" value: {"key":"dedicated-for","operator":"Equal","value":"experiment","effect":"NoSchedule"} - op: add path: "/spec/affinity/nodeAffinity/requiredDuringSchedulingIgnoredDuringExecution/nodeSelectorTerms/-" value: {"matchExpressions": [{"key":"dedicated-for","operator":"In","values":["experiment"]}]} ================================================ FILE: webhosting-operator/config/policy/guaranteed-resources.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: guaranteed-resources spec: failurePolicy: Fail rules: # set resource requests to limits to guarantee the resources during load test experiments - name: guaranteed-resources match: any: - resources: kinds: - Pod namespaces: - experiment - sharding-system - webhosting-system selector: matchExpressions: - key: app.kubernetes.io/name operator: In values: - experiment - controller-sharding - webhosting-operator operations: - CREATE mutate: foreach: - list: request.object.spec.containers patchStrategicMerge: spec: containers: - (name): "{{element.name}}" resources: requests: cpu: "{{element.resources.limits.cpu}}" memory: "{{element.resources.limits.memory}}" ================================================ FILE: webhosting-operator/config/policy/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - experiment-scheduling.yaml - scale-up-worker-experiment.yaml - webhosting-operator-scheduling.yaml - guaranteed-resources.yaml images: - name: pause newName: registry.k8s.io/pause newTag: "3.10" ================================================ FILE: webhosting-operator/config/policy/scale-up-worker-experiment.yaml ================================================ --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: scale-up-worker pool: experiment name: scale-up-worker-experiment namespace: default spec: revisionHistoryLimit: 2 selector: matchLabels: app: scale-up-worker pool: experiment template: metadata: labels: app: scale-up-worker pool: experiment spec: containers: - name: pause image: pause priorityClassName: reserve-excess-capacity tolerations: - key: dedicated-for value: experiment effect: NoSchedule affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: dedicated-for operator: In values: - experiment podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: app: scale-up-worker pool: experiment topologyKey: kubernetes.io/hostname --- apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: reserve-excess-capacity description: PriorityClass for reserving excess capacity (over-provisioning) value: -5 ================================================ FILE: webhosting-operator/config/policy/webhosting-operator-scheduling.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: webhosting-operator-scheduling spec: failurePolicy: Fail rules: # schedule webhosting-operator on dedicated worker pool for better isolation in load tests - name: add-scheduling-constraints match: any: - resources: kinds: - Pod namespaces: - webhosting-system selector: matchLabels: app.kubernetes.io/name: webhosting-operator operations: - CREATE mutate: patchesJson6902: |- - op: add path: "/spec/tolerations/-" value: {"key":"dedicated-for","operator":"Equal","value":"sharding","effect":"NoSchedule"} - op: add path: "/spec/affinity/nodeAffinity/requiredDuringSchedulingIgnoredDuringExecution/nodeSelectorTerms/-" value: {"matchExpressions": [{"key":"dedicated-for","operator":"In","values":["sharding"]}]} ================================================ FILE: webhosting-operator/config/samples/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - project_namespace.yaml - theme_exciting.yaml - theme_lame.yaml - website_kubecon.yaml - website_library.yaml ================================================ FILE: webhosting-operator/config/samples/project_namespace.yaml ================================================ apiVersion: v1 kind: Namespace metadata: name: project-foo labels: webhosting.timebertt.dev/project: "true" ================================================ FILE: webhosting-operator/config/samples/theme_exciting.yaml ================================================ apiVersion: webhosting.timebertt.dev/v1alpha1 kind: Theme metadata: name: exciting spec: color: darkcyan fontFamily: Futura ================================================ FILE: webhosting-operator/config/samples/theme_lame.yaml ================================================ apiVersion: webhosting.timebertt.dev/v1alpha1 kind: Theme metadata: name: lame spec: color: darkgray fontFamily: Times ================================================ FILE: webhosting-operator/config/samples/website_kubecon.yaml ================================================ apiVersion: webhosting.timebertt.dev/v1alpha1 kind: Website metadata: name: kubecon namespace: project-foo spec: theme: exciting ================================================ FILE: webhosting-operator/config/samples/website_library.yaml ================================================ apiVersion: webhosting.timebertt.dev/v1alpha1 kind: Website metadata: name: library namespace: project-foo spec: theme: lame ================================================ FILE: webhosting-operator/config/samples/website_museum.yaml ================================================ apiVersion: webhosting.timebertt.dev/v1alpha1 kind: Website metadata: name: museum namespace: project-foo spec: theme: lame ================================================ FILE: webhosting-operator/go.mod ================================================ module github.com/timebertt/kubernetes-controller-sharding/webhosting-operator go 1.24.0 toolchain go1.25.7 require ( github.com/go-logr/logr v1.4.3 github.com/hashicorp/go-multierror v1.1.1 github.com/onsi/ginkgo/v2 v2.28.1 github.com/onsi/gomega v1.39.1 github.com/prometheus/client_golang v1.23.2 github.com/prometheus/common v0.67.5 github.com/spf13/cobra v1.10.2 github.com/timebertt/kubernetes-controller-sharding v0.0.0 go.uber.org/zap v1.27.1 golang.org/x/time v0.14.0 gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.34.4 k8s.io/apimachinery v0.34.4 k8s.io/client-go v0.34.4 k8s.io/component-base v0.34.4 k8s.io/klog/v2 v2.130.1 k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 sigs.k8s.io/controller-runtime v0.22.5 ) replace github.com/timebertt/kubernetes-controller-sharding => ../ require ( cel.dev/expr v0.24.0 // indirect github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.12.2 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/btree v1.1.3 // indirect github.com/google/cel-go v0.26.0 // indirect github.com/google/gnostic-models v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect github.com/google/uuid v1.6.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/procfs v0.16.1 // indirect github.com/spf13/pflag v1.0.10 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect go.opentelemetry.io/otel v1.35.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect go.opentelemetry.io/otel/metric v1.35.0 // indirect go.opentelemetry.io/otel/sdk v1.34.0 // indirect go.opentelemetry.io/otel/trace v1.35.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect golang.org/x/mod v0.32.0 // indirect golang.org/x/net v0.49.0 // indirect golang.org/x/oauth2 v0.34.0 // indirect golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/term v0.39.0 // indirect golang.org/x/text v0.33.0 // indirect golang.org/x/tools v0.41.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/grpc v1.72.1 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/apiextensions-apiserver v0.34.3 // indirect k8s.io/apiserver v0.34.3 // indirect k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) ================================================ FILE: webhosting-operator/go.sum ================================================ cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs= github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= github.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE= github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI= github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE= github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= k8s.io/api v0.34.4 h1:Z5hsoQcZ2yBjelb9j5JKzCVo9qv9XLkVm5llnqS4h+0= k8s.io/api v0.34.4/go.mod h1:6SaGYuGPkMqqCgg8rPG/OQoCrhgSEV+wWn9v21fDP3o= k8s.io/apiextensions-apiserver v0.34.3 h1:p10fGlkDY09eWKOTeUSioxwLukJnm+KuDZdrW71y40g= k8s.io/apiextensions-apiserver v0.34.3/go.mod h1:aujxvqGFRdb/cmXYfcRTeppN7S2XV/t7WMEc64zB5A0= k8s.io/apimachinery v0.34.4 h1:C5SiSzLEMyWIk53sSbnk0WlOOyqv/MFnWvuc/d6M+xc= k8s.io/apimachinery v0.34.4/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= k8s.io/apiserver v0.34.3 h1:uGH1qpDvSiYG4HVFqc6A3L4CKiX+aBWDrrsxHYK0Bdo= k8s.io/apiserver v0.34.3/go.mod h1:QPnnahMO5C2m3lm6fPW3+JmyQbvHZQ8uudAu/493P2w= k8s.io/client-go v0.34.4 h1:IXhvzFdm0e897kXtLbeyMpAGzontcShJ/gi/XCCsOLc= k8s.io/client-go v0.34.4/go.mod h1:tXIVJTQabT5QRGlFdxZQFxrIhcGUPpKL5DAc4gSWTE8= k8s.io/component-base v0.34.4 h1:jP4XqR48YelfXIlRpOHQgms5GebU23zSE6xcvTwpXDE= k8s.io/component-base v0.34.4/go.mod h1:uujRfLNOwNiFWz47eBjNZEj/Swn2cdhqI7lW2MeFdrU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU= k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/controller-runtime v0.22.5 h1:v3nfSUMowX/2WMp27J9slwGFyAt7IV0YwBxAkrUr0GE= sigs.k8s.io/controller-runtime v0.22.5/go.mod h1:pc5SoYWnWI6I+cBHYYdZ7B6YHZVY5xNfll88JB+vniI= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= ================================================ FILE: webhosting-operator/pkg/apis/config/doc.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ // +groupName=config.webhosting.timebertt.dev package config // import "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/config" ================================================ FILE: webhosting-operator/pkg/apis/config/v1alpha1/defaults.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package v1alpha1 import ( "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/leaderelection/resourcelock" componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1" "k8s.io/utils/ptr" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" ) func addDefaultingFuncs(scheme *runtime.Scheme) error { return RegisterDefaults(scheme) } func SetDefaults_WebhostingOperatorConfig(obj *WebhostingOperatorConfig) { if obj.ClientConnection == nil { obj.ClientConnection = &componentbaseconfigv1alpha1.ClientConnectionConfiguration{} } if obj.LeaderElection == nil { obj.LeaderElection = &componentbaseconfigv1alpha1.LeaderElectionConfiguration{} } if obj.Debugging == nil { obj.Debugging = &componentbaseconfigv1alpha1.DebuggingConfiguration{} } if obj.GracefulShutdownTimeout == nil { var defaultGracefulShutdownTimeout = 15 * time.Second obj.GracefulShutdownTimeout = &metav1.Duration{Duration: defaultGracefulShutdownTimeout} } } func SetDefaults_LeaderElectionConfiguration(obj *componentbaseconfigv1alpha1.LeaderElectionConfiguration) { if obj.ResourceLock == "" { obj.ResourceLock = resourcelock.LeasesResourceLock } componentbaseconfigv1alpha1.RecommendedDefaultLeaderElectionConfiguration(obj) if obj.ResourceName == "" { obj.ResourceName = webhostingv1alpha1.WebhostingOperatorName } if obj.ResourceNamespace == "" { obj.ResourceNamespace = webhostingv1alpha1.NamespaceSystem } } func SetDefaults_DebuggingConfiguration(obj *componentbaseconfigv1alpha1.DebuggingConfiguration) { componentbaseconfigv1alpha1.RecommendedDebuggingConfiguration(obj) if obj.EnableContentionProfiling == nil { obj.EnableContentionProfiling = ptr.To(false) } } func SetDefaults_HealthEndpoint(obj *HealthEndpoint) { if obj.BindAddress == "" { obj.BindAddress = ":8081" } } func SetDefaults_MetricsEndpoint(obj *MetricsEndpoint) { if obj.BindAddress == "" { obj.BindAddress = ":8080" } } ================================================ FILE: webhosting-operator/pkg/apis/config/v1alpha1/doc.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ // +k8s:defaulter-gen=TypeMeta package v1alpha1 // import "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/config/v1alpha1" ================================================ FILE: webhosting-operator/pkg/apis/config/v1alpha1/register.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ // Package v1alpha1 contains API Schema definitions for the config v1alpha1 API group // +kubebuilder:object:generate=true // +groupName=config.webhosting.timebertt.dev package v1alpha1 import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) // GroupName is the group name used in this package. const GroupName = "config.webhosting.timebertt.dev" // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} var ( // SchemeBuilder is a new Scheme Builder which registers our API. SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, addDefaultingFuncs) // AddToScheme is a reference to the Scheme Builder's AddToScheme function. AddToScheme = SchemeBuilder.AddToScheme ) // Adds the list of known types to the given scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &WebhostingOperatorConfig{}, ) return nil } ================================================ FILE: webhosting-operator/pkg/apis/config/v1alpha1/types.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package v1alpha1 import ( networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1" ) //+kubebuilder:object:root=true // WebhostingOperatorConfig is the Schema for the controllermanagerconfigs API type WebhostingOperatorConfig struct { metav1.TypeMeta `json:",inline"` // ClientConnection holds configuration for the kubernetes API clients. // +optional ClientConnection *componentbaseconfigv1alpha1.ClientConnectionConfiguration `json:"clientConnection,omitempty"` // LeaderElection is the LeaderElection config to be used when configuring // the manager.Manager leader election // +optional LeaderElection *componentbaseconfigv1alpha1.LeaderElectionConfiguration `json:"leaderElection,omitempty"` // Debugging holds configuration for Debugging related features. // +optional Debugging *componentbaseconfigv1alpha1.DebuggingConfiguration `json:"debugging,omitempty"` // Health contains the controller health configuration Health HealthEndpoint `json:"health"` // Metrics contains the controller metrics configuration Metrics MetricsEndpoint `json:"metrics"` // GracefulShutdownTimeout is the duration given to runnable to stop before the manager actually returns on stop. // To disable graceful shutdown, set it to 0s. // To use graceful shutdown without timeout, set to a negative duration, e.G. -1s. // The graceful shutdown is skipped for safety reasons in case the leader election lease is lost. // Defaults to 15s GracefulShutdownTimeout *metav1.Duration `json:"gracefulShutDown,omitempty"` // Ingress specifies configuration for the Ingress objects created for Websites. // +optional Ingress *IngressConfiguration `json:"ingress,omitempty"` } // HealthEndpoint defines the health configs. type HealthEndpoint struct { // BindAddress is the TCP address that the controller should bind to // for serving health probes // It can be set to "0" to disable serving the health probe. // Defaults to :8081 // +optional BindAddress string `json:"bindAddress,omitempty"` } // MetricsEndpoint defines the metrics configs. type MetricsEndpoint struct { // 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. // Defaults to :8080 // +optional BindAddress string `json:"bindAddress,omitempty"` } // IngressConfiguration contains configuration for the Ingress objects created for Websites. type IngressConfiguration struct { // Annotations is a set of annotations to add to all created Ingress objects. // +optional Annotations map[string]string `json:"annotations,omitempty"` // Hosts is a list of hosts, under which Websites shall be available. // +optional Hosts []string `json:"hosts,omitempty"` // TLS configures TLS settings to be used on Ingress objects. Specify this to make Websites serve TLS connections for // the given hosts. SecretName is optional. If specified, the given Secret is expected to exist already in all project // namespaces. Otherwise, the Website controller will fill the Ingresses secretName field and expects the secret to be // created and filled by an external controller (e.g. cert-manager). // +optional TLS []networkingv1.IngressTLS `json:"tls,omitempty"` } ================================================ FILE: webhosting-operator/pkg/apis/config/v1alpha1/zz_generated.deepcopy.go ================================================ //go:build !ignore_autogenerated /* Copyright 2023 Tim Ebert. 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. */ // Code generated by controller-gen. DO NOT EDIT. package v1alpha1 import ( networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" configv1alpha1 "k8s.io/component-base/config/v1alpha1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HealthEndpoint) DeepCopyInto(out *HealthEndpoint) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HealthEndpoint. func (in *HealthEndpoint) DeepCopy() *HealthEndpoint { if in == nil { return nil } out := new(HealthEndpoint) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IngressConfiguration) DeepCopyInto(out *IngressConfiguration) { *out = *in if in.Annotations != nil { in, out := &in.Annotations, &out.Annotations *out = make(map[string]string, len(*in)) for key, val := range *in { (*out)[key] = val } } if in.Hosts != nil { in, out := &in.Hosts, &out.Hosts *out = make([]string, len(*in)) copy(*out, *in) } if in.TLS != nil { in, out := &in.TLS, &out.TLS *out = make([]networkingv1.IngressTLS, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressConfiguration. func (in *IngressConfiguration) DeepCopy() *IngressConfiguration { if in == nil { return nil } out := new(IngressConfiguration) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MetricsEndpoint) DeepCopyInto(out *MetricsEndpoint) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricsEndpoint. func (in *MetricsEndpoint) DeepCopy() *MetricsEndpoint { if in == nil { return nil } out := new(MetricsEndpoint) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WebhostingOperatorConfig) DeepCopyInto(out *WebhostingOperatorConfig) { *out = *in out.TypeMeta = in.TypeMeta if in.ClientConnection != nil { in, out := &in.ClientConnection, &out.ClientConnection *out = new(configv1alpha1.ClientConnectionConfiguration) **out = **in } if in.LeaderElection != nil { in, out := &in.LeaderElection, &out.LeaderElection *out = new(configv1alpha1.LeaderElectionConfiguration) (*in).DeepCopyInto(*out) } if in.Debugging != nil { in, out := &in.Debugging, &out.Debugging *out = new(configv1alpha1.DebuggingConfiguration) (*in).DeepCopyInto(*out) } out.Health = in.Health out.Metrics = in.Metrics if in.GracefulShutdownTimeout != nil { in, out := &in.GracefulShutdownTimeout, &out.GracefulShutdownTimeout *out = new(v1.Duration) **out = **in } if in.Ingress != nil { in, out := &in.Ingress, &out.Ingress *out = new(IngressConfiguration) (*in).DeepCopyInto(*out) } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhostingOperatorConfig. func (in *WebhostingOperatorConfig) DeepCopy() *WebhostingOperatorConfig { if in == nil { return nil } out := new(WebhostingOperatorConfig) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *WebhostingOperatorConfig) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } ================================================ FILE: webhosting-operator/pkg/apis/config/v1alpha1/zz_generated.defaults.go ================================================ //go:build !ignore_autogenerated // +build !ignore_autogenerated /* Copyright 2023 Tim Ebert. 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. */ // Code generated by defaulter-gen. DO NOT EDIT. package v1alpha1 import ( runtime "k8s.io/apimachinery/pkg/runtime" ) // RegisterDefaults adds defaulters functions to the given scheme. // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { scheme.AddTypeDefaultingFunc(&WebhostingOperatorConfig{}, func(obj interface{}) { SetObjectDefaults_WebhostingOperatorConfig(obj.(*WebhostingOperatorConfig)) }) return nil } func SetObjectDefaults_WebhostingOperatorConfig(in *WebhostingOperatorConfig) { SetDefaults_WebhostingOperatorConfig(in) if in.LeaderElection != nil { SetDefaults_LeaderElectionConfiguration(in.LeaderElection) } if in.Debugging != nil { SetDefaults_DebuggingConfiguration(in.Debugging) } SetDefaults_HealthEndpoint(&in.Health) SetDefaults_MetricsEndpoint(&in.Metrics) } ================================================ FILE: webhosting-operator/pkg/apis/webhosting/doc.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ // +groupName=webhosting.timebertt.dev package config // import "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting" ================================================ FILE: webhosting-operator/pkg/apis/webhosting/v1alpha1/constants.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package v1alpha1 import ( "k8s.io/apimachinery/pkg/labels" ) const ( // NamespaceSystem is the namespace where the webhosting-operator runs. NamespaceSystem = "webhosting-system" // WebhostingOperatorName is the name of the webhosting-operator Deployment, ControllerRing, etc. WebhostingOperatorName = "webhosting-operator" // LabelKeyProject is the label key on Namespaces for identifying webhosting projects. LabelKeyProject = "webhosting.timebertt.dev/project" // LabelValueProject is the label value for LabelKeyProject on Namespaces for identifying webhosting projects. LabelValueProject = "true" // LabelKeySkipWorkload is the label key on Websites for instructing webhosting-operator to skip any actual workload // for the website. Any value is accepted as truthy. LabelKeySkipWorkload = "skip-workload" ) var ( // LabelSelectorProject is a selector for webhosting project namespaces. LabelSelectorProject = labels.SelectorFromSet(labels.Set{LabelKeyProject: LabelValueProject}) ) ================================================ FILE: webhosting-operator/pkg/apis/webhosting/v1alpha1/doc.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package v1alpha1 // import "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" ================================================ FILE: webhosting-operator/pkg/apis/webhosting/v1alpha1/register.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ // Package v1alpha1 contains API Schema definitions for the webhosting v1alpha1 API group // +kubebuilder:object:generate=true // +groupName=webhosting.timebertt.dev package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) // GroupName is the group name used in this package. const GroupName = "webhosting.timebertt.dev" // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} var ( // SchemeBuilder is a new Scheme Builder which registers our API. SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) // AddToScheme is a reference to the Scheme Builder's AddToScheme function. AddToScheme = SchemeBuilder.AddToScheme ) // Adds the list of known types to the given scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &Website{}, &WebsiteList{}, &Theme{}, &ThemeList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil } ================================================ FILE: webhosting-operator/pkg/apis/webhosting/v1alpha1/types_theme.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // ThemeSpec defines the desired state of a Theme. type ThemeSpec struct { // Color is a CSS color for a Website. Color string `json:"color"` // FontFamily is a font family for a Website. FontFamily string `json:"fontFamily"` } // ThemeStatus defines the observed state of a Theme. type ThemeStatus struct { } //+kubebuilder:object:root=true //+kubebuilder:subresource:status //+kubebuilder:resource:scope=Cluster //+kubebuilder:printcolumn:name="Color",type=string,JSONPath=`.spec.color` //+kubebuilder:printcolumn:name="Font Family",type=string,JSONPath=`.spec.fontFamily` //+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" // Theme is the Schema for the themes API. type Theme struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec contains the specification of the desired behavior of the Theme. // +optional Spec ThemeSpec `json:"spec,omitempty"` // Status contains the most recently observed status of the Theme. // +optional Status ThemeStatus `json:"status,omitempty"` } //+kubebuilder:object:root=true // ThemeList contains a list of Themes. type ThemeList struct { metav1.TypeMeta `json:",inline"` // Standard list metadata. // +optional metav1.ListMeta `json:"metadata,omitempty"` // Items is the list of Themes. Items []Theme `json:"items"` } ================================================ FILE: webhosting-operator/pkg/apis/webhosting/v1alpha1/types_website.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // WebsiteSpec defines the desired state of a Website. type WebsiteSpec struct { // Theme references a Theme object to be used for this Website. Theme string `json:"theme"` } // WebsiteStatus defines the observed state of a Website. type WebsiteStatus struct { // The generation observed by the Website controller. // +optional ObservedGeneration int64 `json:"observedGeneration,omitempty"` // Phase is the current phase of this Website. // +optional Phase WebsitePhase `json:"phase,omitempty"` // LastTransitionTime is the last time the observedGeneration or phase transitioned from one value to another. // +optional LastTransitionTime *metav1.MicroTime `json:"lastTransitionTime,omitempty"` } // WebsitePhase describes the phase of a Website. type WebsitePhase string const ( // PhasePending means that the Website is not ready yet. PhasePending WebsitePhase = "Pending" // PhaseReady means that the Website is ready and available. PhaseReady WebsitePhase = "Ready" // PhaseError means that there is a problem running the Website. PhaseError WebsitePhase = "Error" // PhaseTerminating means that the Website is shutting down. PhaseTerminating WebsitePhase = "Terminating" ) // AllWebsitePhases is a list of all Website phases. var AllWebsitePhases = []WebsitePhase{PhasePending, PhaseReady, PhaseError, PhaseTerminating} //+kubebuilder:object:root=true //+kubebuilder:subresource:status //+kubebuilder:printcolumn:name="Theme",type=string,JSONPath=`.spec.theme` //+kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase` //+kubebuilder:printcolumn:name="Since",type="date",JSONPath=".status.lastTransitionTime" //+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" // Website enables declarative management of hosted websites. type Website struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec contains the specification of the desired behavior of the Website. // +optional Spec WebsiteSpec `json:"spec,omitempty"` // Status contains the most recently observed status of the Website. // +optional Status WebsiteStatus `json:"status,omitempty"` } //+kubebuilder:object:root=true // WebsiteList contains a list of Websites. type WebsiteList struct { metav1.TypeMeta `json:",inline"` // Standard list metadata. // +optional metav1.ListMeta `json:"metadata,omitempty"` // Items is the list of Websites. Items []Website `json:"items"` } ================================================ FILE: webhosting-operator/pkg/apis/webhosting/v1alpha1/zz_generated.deepcopy.go ================================================ //go:build !ignore_autogenerated /* Copyright 2023 Tim Ebert. 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. */ // Code generated by controller-gen. DO NOT EDIT. package v1alpha1 import ( "k8s.io/apimachinery/pkg/runtime" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Theme) DeepCopyInto(out *Theme) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec out.Status = in.Status } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Theme. func (in *Theme) DeepCopy() *Theme { if in == nil { return nil } out := new(Theme) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *Theme) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ThemeList) DeepCopyInto(out *ThemeList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]Theme, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThemeList. func (in *ThemeList) DeepCopy() *ThemeList { if in == nil { return nil } out := new(ThemeList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *ThemeList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ThemeSpec) DeepCopyInto(out *ThemeSpec) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThemeSpec. func (in *ThemeSpec) DeepCopy() *ThemeSpec { if in == nil { return nil } out := new(ThemeSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ThemeStatus) DeepCopyInto(out *ThemeStatus) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThemeStatus. func (in *ThemeStatus) DeepCopy() *ThemeStatus { if in == nil { return nil } out := new(ThemeStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Website) DeepCopyInto(out *Website) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec in.Status.DeepCopyInto(&out.Status) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Website. func (in *Website) DeepCopy() *Website { if in == nil { return nil } out := new(Website) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *Website) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WebsiteList) DeepCopyInto(out *WebsiteList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]Website, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebsiteList. func (in *WebsiteList) DeepCopy() *WebsiteList { if in == nil { return nil } out := new(WebsiteList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *WebsiteList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WebsiteSpec) DeepCopyInto(out *WebsiteSpec) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebsiteSpec. func (in *WebsiteSpec) DeepCopy() *WebsiteSpec { if in == nil { return nil } out := new(WebsiteSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WebsiteStatus) DeepCopyInto(out *WebsiteStatus) { *out = *in if in.LastTransitionTime != nil { in, out := &in.LastTransitionTime, &out.LastTransitionTime *out = (*in).DeepCopy() } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebsiteStatus. func (in *WebsiteStatus) DeepCopy() *WebsiteStatus { if in == nil { return nil } out := new(WebsiteStatus) in.DeepCopyInto(out) return out } ================================================ FILE: webhosting-operator/pkg/controllers/webhosting/suite_test.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package webhosting import ( "path/filepath" "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "k8s.io/client-go/kubernetes/scheme" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" //+kubebuilder:scaffold:imports ) var ( k8sClient client.Client testEnv *envtest.Environment ) func TestController(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Controller Suite") } var _ = BeforeSuite(func() { logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) By("bootstrapping test environment") testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, ErrorIfCRDPathMissing: true, } cfg, err := testEnv.Start() Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) err = webhostingv1alpha1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) //+kubebuilder:scaffold:scheme k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) Expect(err).NotTo(HaveOccurred()) Expect(k8sClient).NotTo(BeNil()) }) var _ = AfterSuite(func() { By("tearing down the test environment") err := testEnv.Stop() Expect(err).NotTo(HaveOccurred()) }) ================================================ FILE: webhosting-operator/pkg/controllers/webhosting/templates/index.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package templates import ( "embed" "fmt" "html/template" "io" "strings" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" ) var ( //go:embed index.tmpl indexTplFS embed.FS // parsed template indexTpl *template.Template ) func init() { var err error indexTpl, err = template.New("index.tmpl").ParseFS(indexTplFS, "*.tmpl") if err != nil { panic(fmt.Errorf("error parsing template: %w", err)) } } // RenderIndexHTML renders the index template and returns it as a string. func RenderIndexHTML(serverName string, website *webhostingv1alpha1.Website, theme *webhostingv1alpha1.Theme) (string, error) { out := &strings.Builder{} err := ExecuteIndexHTMLTemplate(out, serverName, website, theme) return out.String(), err } // ExecuteIndexHTMLTemplate renders the index template and writes it to the given io.Writer. func ExecuteIndexHTMLTemplate(w io.Writer, serverName string, website *webhostingv1alpha1.Website, theme *webhostingv1alpha1.Theme) error { if err := indexTpl.Execute(w, struct { ServerName string Website *webhostingv1alpha1.Website Theme *webhostingv1alpha1.Theme }{serverName, website, theme}); err != nil { return fmt.Errorf("error rendering template: %w", err) } return nil } ================================================ FILE: webhosting-operator/pkg/controllers/webhosting/templates/index.tmpl ================================================ {{ .Website.Name }}

Welcome to {{ .Website.Name }}

Server name: {{ .ServerName }}

This page is hosted on Kubernetes using webhosting-operator.

================================================ FILE: webhosting-operator/pkg/controllers/webhosting/templates/index_test.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package templates_test import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/controllers/webhosting/templates" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/controllers/webhosting/templates/internal" ) var _ = Describe("index.html", func() { It("should successfully render index page", func() { // just assert that the template can be rendered properly Expect(RenderIndexHTML(internal.CreateExamples())).To(ContainSubstring("Welcome to")) }) }) ================================================ FILE: webhosting-operator/pkg/controllers/webhosting/templates/internal/examples.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package internal import ( "k8s.io/apimachinery/pkg/apis/meta/v1" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" ) // CreateExamples returns an example set of values for testing purposes. func CreateExamples() (string, *webhostingv1alpha1.Website, *webhostingv1alpha1.Theme) { return "homepage-381fa2", &webhostingv1alpha1.Website{ ObjectMeta: v1.ObjectMeta{ Name: "homepage", Namespace: "project-foo", }, Spec: webhostingv1alpha1.WebsiteSpec{ Theme: "fancy", }, }, &webhostingv1alpha1.Theme{ ObjectMeta: v1.ObjectMeta{ Name: "fancy", }, Spec: webhostingv1alpha1.ThemeSpec{ Color: "darkcyan", FontFamily: "Menlo", }, } } ================================================ FILE: webhosting-operator/pkg/controllers/webhosting/templates/nginx.conf.tmpl ================================================ server { listen 80; listen [::]:80; server_name localhost; # rewrite /namespace/name to / for requests proxied from Ingress controller # this way, we don't need any Ingress controller specific configuration or objects rewrite ^/{{ .Website.ObjectMeta.Namespace }}/{{ .Website.ObjectMeta.Name }}(.*)$ /$1 last; location / { root /usr/share/nginx/html; index index.html; } } ================================================ FILE: webhosting-operator/pkg/controllers/webhosting/templates/nginx.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package templates import ( "embed" "fmt" "strings" "text/template" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" ) var ( //go:embed nginx.conf.tmpl nginxTplFS embed.FS // parsed template nginxTpl *template.Template ) func init() { var err error nginxTpl, err = template.New("nginx.conf.tmpl").ParseFS(nginxTplFS, "*.tmpl") if err != nil { panic(fmt.Errorf("error parsing template: %w", err)) } } // RenderNginxConf renders the nginx config template and returns it as a string. func RenderNginxConf(serverName string, website *webhostingv1alpha1.Website) (string, error) { out := &strings.Builder{} if err := nginxTpl.Execute(out, struct { ServerName string Website *webhostingv1alpha1.Website }{serverName, website}); err != nil { return "", fmt.Errorf("error rendering template: %w", err) } return out.String(), nil } ================================================ FILE: webhosting-operator/pkg/controllers/webhosting/templates/nginx_test.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package templates_test import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/controllers/webhosting/templates" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/controllers/webhosting/templates/internal" ) var _ = Describe("nginx.conf", func() { const expectedConfig = `server { listen 80; listen [::]:80; server_name localhost; # rewrite /namespace/name to / for requests proxied from Ingress controller # this way, we don't need any Ingress controller specific configuration or objects rewrite ^/project-foo/homepage(.*)$ /$1 last; location / { root /usr/share/nginx/html; index index.html; } } ` It("should successfully render nginx conf", func() { serverName, website, _ := internal.CreateExamples() Expect(RenderNginxConf(serverName, website)).To(Equal(expectedConfig)) }) }) ================================================ FILE: webhosting-operator/pkg/controllers/webhosting/templates/templates_suite_test.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package templates_test import ( "testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func TestTemplates(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "HTML Templates Suite") } ================================================ FILE: webhosting-operator/pkg/controllers/webhosting/templates/testserver/server.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package main import ( "fmt" "net/http" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/controllers/webhosting/templates" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/controllers/webhosting/templates/internal" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { serverName, website, theme := internal.CreateExamples() if err := templates.ExecuteIndexHTMLTemplate(w, serverName, website, theme); err != nil { http.Error(w, fmt.Sprintf("internal server error: %v", err), http.StatusInternalServerError) } }) // nolint:gosec // this is just for testing if err := http.ListenAndServe(":9090", nil); err != nil { panic(err) } } ================================================ FILE: webhosting-operator/pkg/controllers/webhosting/website_controller.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package webhosting import ( "context" "crypto/sha256" "encoding/hex" "errors" "fmt" "maps" "os" "strconv" "github.com/go-logr/logr" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/json" "k8s.io/client-go/tools/record" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" shardcontroller "github.com/timebertt/kubernetes-controller-sharding/pkg/shard/controller" configv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/config/v1alpha1" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/controllers/webhosting/templates" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/utils" ) // WebsiteReconciler reconciles a Website object. type WebsiteReconciler struct { Client client.Client Scheme *runtime.Scheme Recorder record.EventRecorder logger logr.Logger Config *configv1alpha1.WebhostingOperatorConfig } //+kubebuilder:rbac:groups=webhosting.timebertt.dev,resources=websites,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=webhosting.timebertt.dev,resources=websites/status,verbs=get;update;patch //+kubebuilder:rbac:groups=webhosting.timebertt.dev,resources=websites/finalizers,verbs=update //+kubebuilder:rbac:groups=webhosting.timebertt.dev,resources=themes,verbs=get;list;watch //+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;patch //+kubebuilder:rbac:groups="",resources=services,verbs=get;list;watch;create;patch //+kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=get;list;watch;create;patch //+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;patch //+kubebuilder:rbac:groups="",resources=events,verbs=create;patch // RBAC required for sharding //+kubebuilder:rbac:groups=coordination.k8s.io,resources=leases,verbs=get;list;watch;update;patch;delete // Reconcile reconciles a Website object. func (r *WebsiteReconciler) Reconcile(ctx context.Context, website *webhostingv1alpha1.Website) (reconcile.Result, error) { log := logf.FromContext(ctx) log.V(1).Info("Reconciling website") before := website.DeepCopy() // always update the status with the latest observed generation website.Status.ObservedGeneration = website.Generation reconcileErr := r.reconcileWebsite(ctx, log, website) if reconcileErr != nil { website.Status.Phase = webhostingv1alpha1.PhaseError } // update the status if needed if !apiequality.Semantic.DeepEqual(before.Status, website.Status) { website.Status.LastTransitionTime = ptr.To(metav1.NowMicro()) if err := r.Client.Status().Update(ctx, website); err != nil { // unable to update status, requeue with backoff return reconcile.Result{}, errors.Join(reconcileErr, fmt.Errorf("failed updating Website status: %w", err)) } } return reconcile.Result{}, reconcileErr } func (r *WebsiteReconciler) reconcileWebsite(ctx context.Context, log logr.Logger, website *webhostingv1alpha1.Website) error { if website.DeletionTimestamp != nil { // Nothing to do on deletion, all owned objects are cleaned up by the garbage collector. // Set the website's status to terminating and be done with it. // Note: we will only execute this part of the code if the website is deleted with foreground deletion policy, // otherwise it will be gone immediately. website.Status.Phase = webhostingv1alpha1.PhaseTerminating return nil } if website.Spec.Theme == "" { err := r.recordError(website, "ThemeUnspecified", "Website doesn't specify a Theme") // Only requeue with backoff if we fail to update the status. We can't do much till the spec changes, so rather wait // for the next update event. // Log the error and forget the object for now. log.Error(err, "Unable to reconcile Website") return nil } // retrieve theme theme := &webhostingv1alpha1.Theme{} if err := r.Client.Get(ctx, client.ObjectKey{Name: website.Spec.Theme}, theme); err != nil { if apierrors.IsNotFound(err) { return r.recordError(website, "ThemeNotFound", "Theme %s not found", website.Spec.Theme) } return r.recordError(website, reasonReconcilerError, "Error getting Theme %s: %v", website.Spec.Theme, err) } serverName := calculateServerName(website) // create downstream objects configMap, err := r.reconcileConfigMap(ctx, log, serverName, website, theme) if err != nil { return r.recordError(website, reasonReconcilerError, "Error reconciling ConfigMap: %v", err) } if err := r.reconcileService(ctx, log, serverName, website); err != nil { return r.recordError(website, reasonReconcilerError, "Error reconciling Service: %v", err) } if err := r.reconcileIngress(ctx, log, serverName, website); err != nil { return r.recordError(website, reasonReconcilerError, "Error reconciling Ingress: %v", err) } deployment, err := r.reconcileDeployment(ctx, log, serverName, website, configMap) if err != nil { return r.recordError(website, reasonReconcilerError, "Error reconciling Deployment: %v", err) } // update status newPhase := webhostingv1alpha1.PhasePending if utils.IsDeploymentReady(deployment) { newPhase = webhostingv1alpha1.PhaseReady } website.Status.Phase = newPhase return nil } const reasonReconcilerError = "ReconcilerError" func (r *WebsiteReconciler) recordError(website *webhostingv1alpha1.Website, reason, messageFmt string, args ...interface{}) error { r.Recorder.Eventf(website, corev1.EventTypeWarning, reason, messageFmt, args...) // this error can be returned by the reconciler to retry with backoff return fmt.Errorf(messageFmt, args...) } const ( keyIndexHTML = "index.html" keyNginxConf = "nginx.conf" portNameHTTP = "http" ) func (r *WebsiteReconciler) reconcileConfigMap(ctx context.Context, log logr.Logger, serverName string, website *webhostingv1alpha1.Website, theme *webhostingv1alpha1.Theme) (*corev1.ConfigMap, error) { indexHTML, err := templates.RenderIndexHTML(serverName, website, theme) if err != nil { return nil, err } nginxConf, err := templates.RenderNginxConf(serverName, website) if err != nil { return nil, err } configMap := &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{ Name: serverName, Namespace: website.Namespace, }} res, err := controllerutil.CreateOrPatch(ctx, r.Client, configMap, func() error { configMap.Labels = mergeMaps(website.Labels, getLabelsForServer(serverName, website.Name)) configMap.Data = map[string]string{ keyIndexHTML: indexHTML, keyNginxConf: nginxConf, } return controllerutil.SetControllerReference(website, configMap, r.Scheme) }) if res != controllerutil.OperationResultNone { log.V(1).Info("Reconciled ConfigMap", "result", res) } return configMap, err } func (r *WebsiteReconciler) reconcileService(ctx context.Context, log logr.Logger, serverName string, website *webhostingv1alpha1.Website) error { service := &corev1.Service{ObjectMeta: metav1.ObjectMeta{ Name: serverName, Namespace: website.Namespace, }} res, err := controllerutil.CreateOrPatch(ctx, r.Client, service, func() error { service.Labels = mergeMaps(website.Labels, getLabelsForServer(serverName, website.Name)) service.Spec.Type = corev1.ServiceTypeClusterIP service.Spec.Selector = getLabelsForServer(serverName, website.Name) service.Spec.Ports = []corev1.ServicePort{{ Name: portNameHTTP, Port: 8080, TargetPort: intstr.FromString(portNameHTTP), Protocol: corev1.ProtocolTCP, }} return controllerutil.SetControllerReference(website, service, r.Scheme) }) if res != controllerutil.OperationResultNone { log.V(1).Info("Reconciled Service", "result", res) } return err } func (r *WebsiteReconciler) reconcileIngress(ctx context.Context, log logr.Logger, serverName string, website *webhostingv1alpha1.Website) error { ingress := &networkingv1.Ingress{ObjectMeta: metav1.ObjectMeta{ Name: serverName, Namespace: website.Namespace, }} res, err := controllerutil.CreateOrPatch(ctx, r.Client, ingress, func() error { ingress.Labels = mergeMaps(website.Labels, getLabelsForServer(serverName, website.Name)) // base ingress rule value pathType := networkingv1.PathTypePrefix ingressRuleValue := networkingv1.IngressRuleValue{ HTTP: &networkingv1.HTTPIngressRuleValue{ Paths: []networkingv1.HTTPIngressPath{{ Path: fmt.Sprintf("/%s/%s", website.Namespace, website.Name), PathType: &pathType, Backend: networkingv1.IngressBackend{ Service: &networkingv1.IngressServiceBackend{ Name: serverName, Port: networkingv1.ServiceBackendPort{ Name: portNameHTTP, }, }, }, }}, }, } // add default rule without hosts ingress.Spec.Rules = []networkingv1.IngressRule{{ IngressRuleValue: ingressRuleValue, }} applyIngressConfigToIngress(r.Config.Ingress, ingress) if skipWorkload(website) { // don't actually expose website ingresses in load tests // use fake ingress class to prevent overloading ingress controller (this is not what we want to load test) ingress.Spec.IngressClassName = ptr.To("fake") } else if ptr.Deref(ingress.Spec.IngressClassName, "") == "fake" { ingress.Spec.IngressClassName = nil } return controllerutil.SetControllerReference(website, ingress, r.Scheme) }) if res != controllerutil.OperationResultNone { log.V(1).Info("Reconciled Ingress", "result", res) } return err } func applyIngressConfigToIngress(config *configv1alpha1.IngressConfiguration, ingress *networkingv1.Ingress) { if config == nil { config = &configv1alpha1.IngressConfiguration{} } // apply annotations ingress.Annotations = nil for key, value := range config.Annotations { metav1.SetMetaDataAnnotation(&ingress.ObjectMeta, key, value) } // apply hosts if len(config.Hosts) > 0 { // use default rule for each host in config ingressRuleValue := ingress.Spec.Rules[0].IngressRuleValue ingress.Spec.Rules = make([]networkingv1.IngressRule, len(config.Hosts)) for i, host := range config.Hosts { ingress.Spec.Rules[i] = networkingv1.IngressRule{ Host: host, IngressRuleValue: ingressRuleValue, } } } // apply TLS config ingress.Spec.TLS = nil if len(config.TLS) > 0 { ingress.Spec.TLS = make([]networkingv1.IngressTLS, len(config.TLS)) for i, tls := range config.TLS { ingress.Spec.TLS[i] = *tls.DeepCopy() } } } func (r *WebsiteReconciler) reconcileDeployment(ctx context.Context, log logr.Logger, serverName string, website *webhostingv1alpha1.Website, configMap *corev1.ConfigMap) (*appsv1.Deployment, error) { configMapChecksum, err := calculateConfigMapChecksum(configMap) if err != nil { return nil, fmt.Errorf("error calculating checksum of ConfigMap: %w", err) } deployment := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{ Name: serverName, Namespace: website.Namespace, }} res, err := controllerutil.CreateOrPatch(ctx, r.Client, deployment, func() error { deployment.Labels = mergeMaps(website.Labels, getLabelsForServer(serverName, website.Name)) deployment.Spec.Selector = &metav1.LabelSelector{ MatchLabels: getLabelsForServer(serverName, website.Name), } deployment.Spec.RevisionHistoryLimit = ptr.To[int32](2) deployment.Spec.Template.Labels = getLabelsForServer(serverName, website.Name) deployment.Spec.Template.Annotations = map[string]string{ "checksum/configmap": configMapChecksum, } if len(deployment.Spec.Template.Spec.Containers) != 1 { deployment.Spec.Template.Spec.Containers = []corev1.Container{{}} } container := &deployment.Spec.Template.Spec.Containers[0] container.Name = "nginx" container.Image = "nginx:1.29-alpine" container.ImagePullPolicy = corev1.PullIfNotPresent container.Ports = []corev1.ContainerPort{{ Name: portNameHTTP, ContainerPort: 80, Protocol: corev1.ProtocolTCP, }} container.VolumeMounts = []corev1.VolumeMount{{ Name: "website-data", ReadOnly: true, MountPath: "/usr/share/nginx/html", }, { Name: "website-config", ReadOnly: true, MountPath: "/etc/nginx/conf.d", }} deployment.Spec.Template.Spec.Volumes = []corev1.Volume{{ Name: "website-data", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{Name: configMap.Name}, Items: []corev1.KeyToPath{{ Key: keyIndexHTML, Path: "index.html", }}, DefaultMode: ptr.To(corev1.ConfigMapVolumeSourceDefaultMode), }, }, }, { Name: "website-config", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{Name: configMap.Name}, Items: []corev1.KeyToPath{{ Key: keyNginxConf, Path: "nginx.conf", }}, DefaultMode: ptr.To(corev1.ConfigMapVolumeSourceDefaultMode), }, }, }} deployment.Spec.Replicas = ptr.To[int32](1) if skipWorkload(website) { // don't actually run website pods in load tests // otherwise, we would need an immense amount of compute power for running dummy websites deployment.Spec.Replicas = ptr.To[int32](0) } return controllerutil.SetControllerReference(website, deployment, r.Scheme) }) if res != controllerutil.OperationResultNone { log.V(1).Info("Reconciled Deployment", "result", res) } return deployment, err } func getLabelsForServer(serverName, name string) map[string]string { return map[string]string{ "app": "website", "website": name, "server": serverName, "managed-by": webhostingv1alpha1.WebhostingOperatorName, } } func mergeMaps[M interface{ ~map[K]V }, K comparable, V any](mm ...M) M { out := M{} for _, m := range mm { maps.Copy(out, m) } return out } func calculateServerName(website *webhostingv1alpha1.Website) string { // Customers might delete the website and create a new one with the same name. // To avoid clashes in that case, we need to include the website's UID in the name of owned objects. // Take a sha256 sum and include the first 6 hex characters. checksum := sha256.Sum256([]byte(website.UID)) return website.Name + "-" + hex.EncodeToString(checksum[:])[:6] } // calculateConfigMapChecksum calculates a checksum of the given ConfigMap's data. It is supposed to be added to the // pod template to trigger rolling updates on ConfigMap changes. This is to force nginx to reload changed config and // content. func calculateConfigMapChecksum(configMap *corev1.ConfigMap) (string, error) { dataBytes, err := json.Marshal(configMap.Data) if err != nil { return "", err } checksum := sha256.Sum256(dataBytes) return hex.EncodeToString(checksum[:]), nil } const ( ControllerName = "website" websiteThemeField = "spec.theme" ) // SetupWithManager sets up the controller with the Manager. func (r *WebsiteReconciler) SetupWithManager(mgr manager.Manager, enableSharding bool, controllerRingName, shardName string) error { if r.Client == nil { r.Client = mgr.GetClient() } if r.Scheme == nil { r.Scheme = mgr.GetScheme() } if r.Recorder == nil { r.Recorder = mgr.GetEventRecorderFor(ControllerName + "-controller") } if err := mgr.GetCache().IndexField(context.TODO(), &webhostingv1alpha1.Website{}, websiteThemeField, func(obj client.Object) []string { return []string{obj.(*webhostingv1alpha1.Website).Spec.Theme} }); err != nil { return err } workers := 15 if override, err := strconv.ParseInt(os.Getenv("WEBSITE_CONCURRENT_SYNCS"), 10, 32); err == nil { workers = int(override) } var ( // trigger on spec, status, and annotation changes (manual trigger for testing purposes) websitePredicate = predicate.Or( predicate.GenerationChangedPredicate{}, predicate.AnnotationChangedPredicate{}, WebsiteStatusChanged, ) reconciler = reconcile.AsReconciler[*webhostingv1alpha1.Website](r.Client, r) ) if enableSharding { // ACKNOWLEDGE DRAIN OPERATIONS // Use the shardcontroller package as helpers for: // - a predicate that triggers when the drain label is present (even if the actual predicates don't trigger) websitePredicate = shardcontroller.Predicate(controllerRingName, shardName, websitePredicate) // - wrapping the actual reconciler a reconciler that handles the drain operation for us reconciler = shardcontroller.NewShardedReconciler(mgr). For(&webhostingv1alpha1.Website{}). InControllerRing(controllerRingName). WithShardName(shardName). MustBuild(reconciler) } c, err := builder.ControllerManagedBy(mgr). Named(ControllerName). For(&webhostingv1alpha1.Website{}, builder.WithPredicates(websitePredicate)). // watch deployments in order to update phase on relevant changes // watch deployments for relevant changes to reconcile them back if changed Owns(&appsv1.Deployment{}, builder.WithPredicates(predicate.Or( predicate.GenerationChangedPredicate{}, DeploymentAvailabilityChanged, ))). // watch owned objects for relevant changes to reconcile them back if changed Owns(&corev1.ConfigMap{}, builder.WithPredicates(ConfigMapDataChanged)). Owns(&corev1.Service{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})). Owns(&networkingv1.Ingress{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})). // watch themes to roll out theme changes to all referencing websites Watches( &webhostingv1alpha1.Theme{}, handler.EnqueueRequestsFromMapFunc(r.MapThemeToWebsites), builder.WithPredicates(predicate.GenerationChangedPredicate{}), ). WithOptions(controller.Options{ MaxConcurrentReconciles: workers, }). Build(reconciler) if err != nil { return err } r.logger = c.GetLogger() return nil } // MapThemeToWebsites maps a theme to all websites that use it. func (r *WebsiteReconciler) MapThemeToWebsites(ctx context.Context, theme client.Object) []reconcile.Request { websiteList := &webhostingv1alpha1.WebsiteList{} if err := r.Client.List(ctx, websiteList, client.MatchingFields{websiteThemeField: theme.GetName()}); err != nil { r.logger.Error(err, "failed to list websites belonging to theme", "theme", client.ObjectKeyFromObject(theme)) return []reconcile.Request{} } requests := make([]reconcile.Request, len(websiteList.Items)) for i, website := range websiteList.Items { requests[i] = reconcile.Request{ NamespacedName: types.NamespacedName{ Name: website.GetName(), Namespace: website.GetNamespace(), }, } } return requests } // WebsiteStatusChanged is a predicate that triggers when the Website status changes. // The controller skips updating the status if it didn't change the cached object. In fast consecutive retries, this // can lead to a Website in Error state, where the controller doesn't observe its own status update, and skips the // transition to Ready afterward because the cached object was still in Ready state. // To fix this, we trigger the controller one more time when observing its own status updates to ensure a correct // status. This shouldn't hurt the standard case, because the controller doesn't cause any API calls if not needed. var WebsiteStatusChanged = predicate.Funcs{ UpdateFunc: func(e event.UpdateEvent) bool { if e.ObjectOld == nil || e.ObjectNew == nil { return false } oldWebsite, ok := e.ObjectOld.(*webhostingv1alpha1.Website) if !ok { return false } newWebsite, ok := e.ObjectNew.(*webhostingv1alpha1.Website) if !ok { return false } return !apiequality.Semantic.DeepEqual(oldWebsite.Status, newWebsite.Status) }, } // DeploymentAvailabilityChanged is a predicate for filtering relevant Deployment events. var DeploymentAvailabilityChanged = predicate.Funcs{ UpdateFunc: func(e event.UpdateEvent) bool { if e.ObjectOld == nil || e.ObjectNew == nil { return false } oldDeployment, ok := e.ObjectOld.(*appsv1.Deployment) if !ok { return false } newDeployment, ok := e.ObjectNew.(*appsv1.Deployment) if !ok { return false } return utils.IsDeploymentReady(oldDeployment) != utils.IsDeploymentReady(newDeployment) }, } // ConfigMapDataChanged is a predicate for filtering relevant ConfigMap events. // Similar to predicate.GenerationChangedPredicate (ConfigMaps don't have a generation). var ConfigMapDataChanged = predicate.Funcs{ UpdateFunc: func(e event.UpdateEvent) bool { if e.ObjectOld == nil || e.ObjectNew == nil { return false } oldConfigMap, ok := e.ObjectOld.(*corev1.ConfigMap) if !ok { return false } newConfigMap, ok := e.ObjectNew.(*corev1.ConfigMap) if !ok { return false } return !apiequality.Semantic.DeepEqual(oldConfigMap.Data, newConfigMap.Data) }, } // skipWorkload returns true if the controller should not run any actual workload for this Website, e.g., for load tests // or e2e tests. func skipWorkload(website *webhostingv1alpha1.Website) bool { _, ok := website.Labels[webhostingv1alpha1.LabelKeySkipWorkload] return ok } ================================================ FILE: webhosting-operator/pkg/experiment/generator/options.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package generator import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type GenerateOption interface { ApplyToOptions(options *GenerateOptions) } type GenerateOptions struct { Labels map[string]string OwnerReference *metav1.OwnerReference } func (o *GenerateOptions) ApplyOptions(opts ...GenerateOption) *GenerateOptions { for _, opt := range opts { opt.ApplyToOptions(o) } return o } func (o *GenerateOptions) ApplyToOptions(options *GenerateOptions) { if len(o.Labels) > 0 { if options.Labels == nil { options.Labels = make(map[string]string, len(o.Labels)) } for k, v := range o.Labels { options.Labels[k] = v } } if ownerRef := o.OwnerReference; ownerRef != nil { options.OwnerReference = ownerRef.DeepCopy() } } func (o *GenerateOptions) ApplyToObject(obj *metav1.ObjectMeta) { for k, v := range o.Labels { metav1.SetMetaDataLabel(obj, k, v) } if ownerRef := o.OwnerReference; ownerRef != nil { obj.OwnerReferences = append(obj.OwnerReferences, *ownerRef) } } type GenerateOptionFunc func(options *GenerateOptions) func (f GenerateOptionFunc) ApplyToOptions(options *GenerateOptions) { f(options) } func WithLabels(labels map[string]string) GenerateOption { return GenerateOptionFunc(func(options *GenerateOptions) { if options.Labels == nil { options.Labels = make(map[string]string, len(labels)) } for k, v := range labels { options.Labels[k] = v } }) } func WithOwnerReference(ownerRef *metav1.OwnerReference) GenerateOption { return GenerateOptionFunc(func(options *GenerateOptions) { options.OwnerReference = ownerRef.DeepCopy() }) } ================================================ FILE: webhosting-operator/pkg/experiment/generator/project.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package generator import ( "context" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" ) // CreateProjects creates n random project namespaces. func CreateProjects(ctx context.Context, c client.Client, n int, opts ...GenerateOption) error { return NTimesConcurrently(n, 10, func() error { return RetryOnError(ctx, 5, func(ctx context.Context) error { return CreateProject(ctx, c, opts...) }, apierrors.IsAlreadyExists) }) } // CreateProject creates a random project namespace. func CreateProject(ctx context.Context, c client.Client, opts ...GenerateOption) error { options := (&GenerateOptions{}).ApplyOptions(opts...) namespace := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "project-", Labels: map[string]string{ webhostingv1alpha1.LabelKeyProject: webhostingv1alpha1.LabelValueProject, }, }, } options.ApplyToObject(&namespace.ObjectMeta) if err := c.Create(ctx, namespace); err != nil { return err } log.V(1).Info("Created project namespace", "namespaceName", namespace.Name) return nil } // CleanupProjects deletes all namespaces with the given labels. func CleanupProjects(ctx context.Context, c client.Client, labels map[string]string) error { namespaceList := &corev1.NamespaceList{} if err := c.List(ctx, namespaceList, client.MatchingLabels(labels)); err != nil { return err } for _, namespace := range namespaceList.Items { if err := c.Delete(ctx, &namespace); err != nil { return err } } log.V(1).Info("Cleaned up all project namespaces") return nil } ================================================ FILE: webhosting-operator/pkg/experiment/generator/reconciler.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package generator import ( "context" "reflect" "time" "golang.org/x/time/rate" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/workqueue" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) const defaultReconcileWorkers = 10 // Every runs the given Func with the specified frequency. type Every struct { client.Client Name string Do func(ctx context.Context, c client.Client) error Rate rate.Limit Stop time.Time Workers int } func (r *Every) AddToManager(mgr manager.Manager) error { if r.Client == nil { r.Client = mgr.GetClient() } initialDelay := time.Duration(0) workers := defaultReconcileWorkers if r.Workers > 0 { workers = r.Workers } var rateLimiter workqueue.TypedRateLimiter[reconcile.Request] = &workqueue.TypedBucketRateLimiter[reconcile.Request]{ Limiter: rate.NewLimiter(r.Rate, int(r.Rate)), } if r.Rate < 1 { // Special case for controllers running less frequent than every second: // The token bucket rate limiter would not allow any events as burst is less than 1, so replace it with a custom // rate limiter that always returns a constant delay. // Also, delay the first request when starting the scenario. every := time.Duration(1 / float64(r.Rate) * float64(time.Second)) rateLimiter = constantDelayRateLimiter(every) initialDelay = every workers = 1 } return builder.ControllerManagedBy(mgr). Named(r.Name). WithOptions(controller.Options{ MaxConcurrentReconciles: workers, RateLimiter: rateLimiter, }). WatchesRawSource(EmitN(workers, initialDelay)). Complete(StopOnContextCanceled(r)) } func (r *Every) Reconcile(ctx context.Context, _ reconcile.Request) (reconcile.Result, error) { if !r.Stop.IsZero() && !time.Now().Before(r.Stop) { // stop now return reconcile.Result{}, nil } return reconcile.Result{Requeue: true}, r.Do(ctx, r.Client) } // ForEach runs the given Func for each object of the given kind with the specified frequency. // The first execution runs Every after object creation. type ForEach[T client.Object] struct { client.Client Name string Do func(ctx context.Context, c client.Client, obj T) error Every time.Duration Stop time.Time Workers int gvk schema.GroupVersionKind obj T } func (r *ForEach[T]) AddToManager(mgr manager.Manager) error { if r.Client == nil { r.Client = mgr.GetClient() } var t T r.obj = reflect.New(reflect.TypeOf(t).Elem()).Interface().(T) var err error r.gvk, err = apiutil.GVKForObject(r.obj, mgr.GetScheme()) if err != nil { return err } workers := defaultReconcileWorkers if r.Workers > 0 { workers = r.Workers } return builder.ControllerManagedBy(mgr). Named(r.Name). WithOptions(controller.Options{ MaxConcurrentReconciles: workers, RateLimiter: unlimitedRateLimiter(), }). Watches( r.obj, &handler.Funcs{ // only enqueue create events, after that we reconcile periodically CreateFunc: func(ctx context.Context, e event.CreateEvent, q workqueue.TypedRateLimitingInterface[reconcile.Request]) { if e.Object == nil { return } // we should not enqueue directly on creation, but only after Every has passed for the first time q.AddAfter(reconcile.Request{NamespacedName: types.NamespacedName{ Name: e.Object.GetName(), Namespace: e.Object.GetNamespace(), }}, r.Every) }, }, ). Complete(StopOnContextCanceled(r)) } func (r *ForEach[T]) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { if !r.Stop.IsZero() && !time.Now().Before(r.Stop) { // stop now return reconcile.Result{}, nil } obj := r.obj.DeepCopyObject().(T) if err := r.Get(ctx, request.NamespacedName, obj); err != nil { if apierrors.IsNotFound(err) { return reconcile.Result{}, nil } return reconcile.Result{}, err } return reconcile.Result{RequeueAfter: r.Every}, r.Do(ctx, r.Client, obj) } // unlimitedRateLimiter returns a RateLimiter that doesn't apply any rate limits to the workqueue. func unlimitedRateLimiter() workqueue.TypedRateLimiter[reconcile.Request] { // if no limiter is given, MaxOfRateLimiter returns 0 for When and NumRequeues => unlimited return &workqueue.TypedMaxOfRateLimiter[reconcile.Request]{} } ================================================ FILE: webhosting-operator/pkg/experiment/generator/theme.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package generator import ( "context" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/utils" ) var ( themeColors = []string{"aqua", "black", "blue", "fuchsia", "gray", "green", "lime", "maroon", "navy", "olive", "orange", "purple", "red", "silver", "teal", "white", "yellow"} themeFonts = []string{"Arial", "Verdana", "Tahoma", "Trebuchet MS", "Times New Roman", "Georgia", "Garamond", "Courier New", "Brush Script MT"} ) // CreateThemes creates n random themes. func CreateThemes(ctx context.Context, c client.Client, n int, opts ...GenerateOption) error { return NTimesConcurrently(n, 10, func() error { return RetryOnError(ctx, 5, func(ctx context.Context) error { return CreateTheme(ctx, c, opts...) }, apierrors.IsAlreadyExists) }) } // CreateTheme creates a random theme. func CreateTheme(ctx context.Context, c client.Client, opts ...GenerateOption) error { options := (&GenerateOptions{}).ApplyOptions(opts...) theme := &webhostingv1alpha1.Theme{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "theme-", }, Spec: webhostingv1alpha1.ThemeSpec{ Color: utils.PickRandom(themeColors), FontFamily: utils.PickRandom(themeFonts), }, } options.ApplyToObject(&theme.ObjectMeta) if err := c.Create(ctx, theme); err != nil { return err } log.V(1).Info("Created theme", "themeName", theme.Name) return nil } // MutateTheme mutates the given theme using the given client and labels. func MutateTheme(ctx context.Context, c client.Client, theme *webhostingv1alpha1.Theme) error { patch := client.MergeFrom(theme.DeepCopy()) theme.Spec.Color = utils.PickRandom(themeColors) theme.Spec.FontFamily = utils.PickRandom(themeFonts) if err := c.Patch(ctx, theme, patch); err != nil { return err } log.V(1).Info("Mutated theme", "themeName", theme.Name) return nil } // MutateRandomTheme mutates a random existing theme using the given client and labels. func MutateRandomTheme(ctx context.Context, c client.Client, labels map[string]string) error { themeList := &webhostingv1alpha1.ThemeList{} if err := c.List(ctx, themeList, client.MatchingLabels(labels)); err != nil { return err } if len(themeList.Items) == 0 { log.V(1).Info("No themes found, skipping mutation") return nil } theme := utils.PickRandom(themeList.Items) return MutateTheme(ctx, c, &theme) } ================================================ FILE: webhosting-operator/pkg/experiment/generator/utils.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package generator import ( "context" "errors" "fmt" "sync" "time" "github.com/hashicorp/go-multierror" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/util/workqueue" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" ) var log = logf.Log // EmitN returns a source that emits exactly n reconcile requests with the given delay. // Use it with the controller builder: // // WatchesRawSource(EmitN(n, time.Second)) // // Or a plain controller: // // Watch(EmitN(n, time.Second)) func EmitN(n int, delay time.Duration) source.Source { return source.TypedFunc[reconcile.Request](func(ctx context.Context, queue workqueue.TypedRateLimitingInterface[reconcile.Request]) error { for i := 0; i < n; i++ { queue.AddAfter(reconcile.Request{NamespacedName: types.NamespacedName{ // use different object names, otherwise queue will merge the requests Name: fmt.Sprintf("request-%d", n), }}, delay) } return nil }) } // StopOnContextCanceled wraps the given reconciler so that "context canceled" errors are ignored. This is helpful when // a reconciler is expected to be canceled (e.g., when the scenario finishes). We neither need to retry nor log on such // errors. We can just stop silently. func StopOnContextCanceled(r reconcile.Reconciler) reconcile.Reconciler { return reconcile.Func(func(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { result, err := r.Reconcile(ctx, request) if errors.Is(err, context.Canceled) { return reconcile.Result{}, nil } return result, err }) } // NTimesConcurrently runs the given action n times. It distributes the work across the given number of concurrent // workers. func NTimesConcurrently(n, workers int, do func() error) error { var ( wg sync.WaitGroup work = make(chan struct{}, workers) errs = make(chan error, workers) ) // start workers for i := 0; i < workers; i++ { wg.Add(1) go func() { defer wg.Done() for range work { errs <- do() } }() } // collect all errors var ( allErrs *multierror.Error errsDone = make(chan struct{}) ) go func() { for err := range errs { allErrs = multierror.Append(allErrs, err) } close(errsDone) }() // emit n work items for i := 0; i < n; i++ { work <- struct{}{} } close(work) // wait for all workers to process all work items wg.Wait() // signal error worker and wait for it to process all errors close(errs) <-errsDone return allErrs.ErrorOrNil() } // RetryOnError runs the given action with a short timeout and retries it up to `retries` times if it retruns a // retriable error. // This is useful when creating a lot of objects in parallel with generateName which can lead to AlreadyExists errors. func RetryOnError(ctx context.Context, retries int, do func(context.Context) error, retriable func(error) bool) error { i := 0 return wait.PollUntilContextTimeout(ctx, 50*time.Millisecond, 10*time.Second, true, func(ctx context.Context) (done bool, err error) { err = do(ctx) if err == nil { return true, nil } // stop retrying on non-retriable errors if !retriable(err) { return true, err } // stop retrying when reaching the max retry count i++ if i > retries { return true, err } // otherwise, retry another time return false, nil }) } // CreateClusterScopedOwnerObject creates a new cluster-scoped object that has a single purpose: being used as an owner // for multiple objects that should be cleaned up at once. This is useful for cleaning up a lot of objects (of different // kinds) at once with a single DELETE call. func CreateClusterScopedOwnerObject(ctx context.Context, c client.Client, opts ...GenerateOption) (client.Object, *metav1.OwnerReference, error) { options := (&GenerateOptions{}).ApplyOptions(opts...) ownerObject := &rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "experiment-owner-", }, } options.ApplyToObject(&ownerObject.ObjectMeta) if err := c.Create(ctx, ownerObject); err != nil { return nil, nil, err } return ownerObject, metav1.NewControllerRef(ownerObject, rbacv1.SchemeGroupVersion.WithKind("ClusterRole")), nil } var _ workqueue.TypedRateLimiter[reconcile.Request] = constantDelayRateLimiter(0) // constantDelayRateLimiter delays all requests with a constant duration. type constantDelayRateLimiter time.Duration func (d constantDelayRateLimiter) When(reconcile.Request) time.Duration { return time.Duration(d) } func (d constantDelayRateLimiter) Forget(reconcile.Request) {} func (d constantDelayRateLimiter) NumRequeues(reconcile.Request) int { return 0 } ================================================ FILE: webhosting-operator/pkg/experiment/generator/website.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package generator import ( "context" "fmt" "sync" "time" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/utils" ) var ( websiteTracker WebsiteTracker websiteTrackerOnce sync.Once ) type WebsiteTracker interface { RecordSpecChange(website *webhostingv1alpha1.Website) } // SetWebsiteTracker sets up this package to track website creations and spec updates with the given tracker. func SetWebsiteTracker(tracker WebsiteTracker) { websiteTrackerOnce.Do(func() { websiteTracker = tracker }) } // CreateWebsites creates n random websites. func CreateWebsites(ctx context.Context, c client.Client, n int, opts ...GenerateOption) error { return NTimesConcurrently(n, 10, func() error { return RetryOnError(ctx, 5, func(ctx context.Context) error { return CreateWebsite(ctx, c, opts...) }, apierrors.IsAlreadyExists) }) } // CreateWebsite creates a random website. func CreateWebsite(ctx context.Context, c client.Client, opts ...GenerateOption) error { options := (&GenerateOptions{}).ApplyOptions(opts...) // pick random theme and project for a new website themeList := &webhostingv1alpha1.ThemeList{} if err := c.List(ctx, themeList, client.MatchingLabels(options.Labels)); err != nil { return err } if len(themeList.Items) == 0 { log.V(1).Info("No themes found, skipping creation") return nil } namespaceList := &corev1.NamespaceList{} if err := c.List(ctx, namespaceList, client.MatchingLabels(options.Labels)); err != nil { return err } if len(namespaceList.Items) == 0 { return fmt.Errorf("no namespaces found, cannot create website") } website := &webhostingv1alpha1.Website{ ObjectMeta: metav1.ObjectMeta{ Name: "experiment-" + utils.RandomName(8), Namespace: utils.PickRandom(namespaceList.Items).Name, }, Spec: webhostingv1alpha1.WebsiteSpec{ Theme: utils.PickRandom(themeList.Items).Name, }, } options.ApplyToObject(&website.ObjectMeta) if err := c.Create(ctx, website); err != nil { return err } log.V(1).Info("Created website", "website", client.ObjectKeyFromObject(website)) if websiteTracker != nil { websiteTracker.RecordSpecChange(website) } return nil } // MutateWebsite mutates the given website using the given client and labels. func MutateWebsite(ctx context.Context, c client.Client, website *webhostingv1alpha1.Website, labels map[string]string) error { // pick new random theme for the website themeList := &webhostingv1alpha1.ThemeList{} if err := c.List(ctx, themeList, client.MatchingLabels(labels)); err != nil { return err } if len(themeList.Items) == 0 { log.V(1).Info("No themes found, skipping mutation") return nil } patch := client.MergeFrom(website.DeepCopy()) website.Spec.Theme = utils.PickRandom(themeList.Items).Name if err := c.Patch(ctx, website, patch); err != nil { return err } log.V(1).Info("Mutated website", "website", client.ObjectKeyFromObject(website)) if websiteTracker != nil { websiteTracker.RecordSpecChange(website) } return nil } // ReconcileWebsite triggers reconciliation of the given website by updating an annotation. func ReconcileWebsite(ctx context.Context, c client.Client, website *webhostingv1alpha1.Website) error { patch := client.MergeFrom(website.DeepCopy()) metav1.SetMetaDataAnnotation(&website.ObjectMeta, "experiment-reconcile", time.Now().UTC().Format(time.RFC3339)) if err := c.Patch(ctx, website, patch); err != nil { return err } log.V(1).Info("Triggered reconciliation of website", "website", client.ObjectKeyFromObject(website)) return nil } // DeleteWebsite deletes a random existing website using the given client and labels. func DeleteWebsite(ctx context.Context, c client.Client, labels map[string]string) error { websiteList := &webhostingv1alpha1.WebsiteList{} if err := c.List(ctx, websiteList, client.MatchingLabels(labels)); err != nil { return err } if len(websiteList.Items) == 0 { log.V(1).Info("No websites found, skipping deletion") return nil } website := utils.PickRandom(websiteList.Items) if err := c.Delete(ctx, &website); err != nil { return err } log.V(1).Info("Deleted website", "website", client.ObjectKeyFromObject(&website)) return nil } ================================================ FILE: webhosting-operator/pkg/experiment/scenario/all/all.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ // Package all imports all scenarios. package all import ( _ "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/scenario/basic" _ "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/scenario/chaos" _ "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/scenario/rolling-update" _ "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/scenario/scale-out" ) ================================================ FILE: webhosting-operator/pkg/experiment/scenario/base/base.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package base import ( "context" "errors" "fmt" "os" "time" "github.com/go-logr/logr" appsv1 "k8s.io/api/apps/v1" coordinationv1 "k8s.io/api/coordination/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/generator" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/tracker" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/utils" ) // Scenario provides a common base implemenation for parts of the experiment.Scenario interface. type Scenario struct { // Delegate is responsible for performing the actual experiment actions. Delegate Delegate ScenarioName string Log logr.Logger Manager manager.Manager Client client.Client done chan struct{} RunID string Labels map[string]string OwnerRef *metav1.OwnerReference } // Delegate combines the actual experiment actions in a single interface. type Delegate interface { Prepare(ctx context.Context) error Run(ctx context.Context) error } func (s *Scenario) Name() string { return s.ScenarioName } func (s *Scenario) Done() <-chan struct{} { return s.done } func (s *Scenario) AddToManager(mgr manager.Manager) error { s.Log = logf.Log.WithName("scenario").WithName(s.ScenarioName) s.Manager = mgr s.Client = mgr.GetClient() s.done = make(chan struct{}) s.Labels = map[string]string{ "generated-by": "experiment", "scenario": s.ScenarioName, webhostingv1alpha1.LabelKeySkipWorkload: "true", } return mgr.Add(s) } func (s *Scenario) Start(ctx context.Context) (err error) { defer close(s.done) s.Log.Info("Scenario started") cleanup, err := s.prepare(ctx) if err != nil { return err } defer func() { s.Log.Info("Cleaning up") cleanupCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if cleanupErr := cleanup(cleanupCtx); cleanupErr != nil { // if another error occurred during execution, it has priority // otherwise, return the cleanup error if err != nil { s.Log.Error(cleanupErr, "Failed cleaning up") } else { err = cleanupErr } return } s.Log.Info("Cleanup done") }() if err := s.Delegate.Prepare(ctx); err != nil { return err } s.Log.Info("Scenario prepared") // give monitoring stack some time to observe objects select { case <-ctx.Done(): s.Log.Info("Scenario canceled") return ctx.Err() case <-time.After(30 * time.Second): } websiteTracker := &tracker.WebsiteTracker{} if err := websiteTracker.AddToManager(s.Manager); err != nil { return fmt.Errorf("error adding website-tracker: %w", err) } generator.SetWebsiteTracker(websiteTracker) s.Log.Info("Scenario running") if err := s.Delegate.Run(ctx); err != nil { return err } s.Log.Info("Scenario finished") return nil } func (s *Scenario) prepare(ctx context.Context) (func(context.Context) error, error) { // determine run ID // env var can be specified in the pod spec, e.g. from the pod's uid so that experiment's own metrics can be selected // by run ID s.RunID = os.Getenv("RUN_ID") if s.RunID == "" { s.RunID = string(uuid.NewUUID()) } // use unique label set per scenario run s.Labels["run-id"] = s.RunID s.Log = s.Log.WithValues("run-id", s.RunID) s.Log.Info("Creating owner object") ownerObject, ownerRef, err := generator.CreateClusterScopedOwnerObject(ctx, s.Client, generator.WithLabels(s.Labels)) if err != nil { return nil, err } s.OwnerRef = ownerRef s.Log.Info("Created owner object", "object", ownerObject) cleanup := func(cleanupCtx context.Context) error { if err := s.Client.Delete(cleanupCtx, ownerObject, client.PropagationPolicy(metav1.DeletePropagationForeground)); err != nil { return fmt.Errorf("failed cleaning up owner object %T %s", ownerObject, client.ObjectKeyFromObject(ownerObject)) } return nil } // Label all observed components with the experiment's run ID to trigger a rollout (start from a fresh state). // The run ID is added to all scraped metrics in the ServiceMonitor. // This allows calculating rates of individual runs without considering metrics of adjacent runs. s.Log.Info("Restarting/labeling observed components") observedComponents := []struct{ namespace, name string }{ {shardingv1alpha1.NamespaceSystem, "sharder"}, {webhostingv1alpha1.NamespaceSystem, webhostingv1alpha1.WebhostingOperatorName}, } for _, c := range observedComponents { if err := s.injectRunIDLabel(ctx, c.namespace, c.name); err != nil { return nil, err } } // wait for all observed components to be rolled out and ready again for _, c := range observedComponents { if err := s.waitForDeployment(ctx, c.namespace, c.name); err != nil { return nil, fmt.Errorf("failed waiting for deployment: %w", err) } } // clean up orphaned leases after instances have been terminated // this only speeds up the cleaning and allows us to start sooner, but is not required otherwise if err := s.Client.DeleteAllOf(ctx, &coordinationv1.Lease{}, client.InNamespace(webhostingv1alpha1.NamespaceSystem), client.MatchingLabels{"alpha.sharding.timebertt.dev/state": "dead"}, ); err != nil { return nil, err } // wait for all shard leases to be ready if err := s.waitForShardLeases(ctx); err != nil { return nil, fmt.Errorf("failed waiting for shard leases: %w", err) } return cleanup, nil } func (s *Scenario) injectRunIDLabel(ctx context.Context, namespace, name string) error { deployment := &appsv1.Deployment{} if err := s.Client.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, deployment); err != nil { return err } patch := client.MergeFrom(deployment.DeepCopy()) metav1.SetMetaDataLabel(&deployment.Spec.Template.ObjectMeta, "label.prometheus.io/run_id", s.RunID) return s.Client.Patch(ctx, deployment, patch) } func (s *Scenario) waitForDeployment(ctx context.Context, namespace, name string) error { var lastError error if err := wait.PollUntilContextTimeout(ctx, 2*time.Second, 2*time.Minute, false, func(ctx context.Context) (done bool, err error) { deployment := &appsv1.Deployment{} if err := s.Client.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, deployment); err != nil { return true, err } if !utils.IsDeploymentReady(deployment) { lastError = fmt.Errorf("deployment %s is not available", client.ObjectKeyFromObject(deployment)) return false, nil } return true, nil }); err != nil { if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { return lastError } return err } return nil } func (s *Scenario) waitForShardLeases(ctx context.Context) error { var lastError error if err := wait.PollUntilContextTimeout(ctx, 2*time.Second, 2*time.Minute, false, func(ctx context.Context) (done bool, err error) { leaseList := &coordinationv1.LeaseList{} if err := s.Client.List(ctx, leaseList, client.InNamespace(webhostingv1alpha1.NamespaceSystem), client.MatchingLabels{shardingv1alpha1.LabelControllerRing: webhostingv1alpha1.WebhostingOperatorName}, ); err != nil { return true, err } for _, lease := range leaseList.Items { state := lease.Labels["alpha.sharding.timebertt.dev/state"] if state != "ready" { lastError = fmt.Errorf("shard lease %s is in state %q", client.ObjectKeyFromObject(&lease), state) return false, nil } } return true, nil }); err != nil { if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { return lastError } return err } return nil } // Wait does blocks until the given duration has passed or returns an error when the context is canceled. func (s *Scenario) Wait(ctx context.Context, d time.Duration) error { select { case <-ctx.Done(): s.Log.Info("Scenario canceled") return ctx.Err() case <-time.After(d): } return nil } ================================================ FILE: webhosting-operator/pkg/experiment/scenario/basic/basic.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package basic import ( "context" "fmt" "time" "golang.org/x/time/rate" "sigs.k8s.io/controller-runtime/pkg/client" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/generator" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/scenario/base" ) const ScenarioName = "basic" func init() { s := &scenario{} s.Scenario = &base.Scenario{ ScenarioName: ScenarioName, Delegate: s, } experiment.RegisterScenario(s) } type scenario struct { *base.Scenario } func (s *scenario) Description() string { return "Basic load test, create 9k websites in 15 minutes" } func (s *scenario) LongDescription() string { return `The ` + ScenarioName + ` scenario combines several operations typical for a lively operator environment: - website creation: 10800 over 15m - website deletion: 1800 over 15m - website spec changes: 1/m per object, max 150/s ` } func (s *scenario) Prepare(ctx context.Context) error { s.Log.Info("Preparing themes") if err := generator.CreateThemes(ctx, s.Client, 50, generator.WithLabels(s.Labels), generator.WithOwnerReference(s.OwnerRef)); err != nil { return err } s.Log.Info("Preparing projects") if err := generator.CreateProjects(ctx, s.Client, 20, generator.WithLabels(s.Labels), generator.WithOwnerReference(s.OwnerRef)); err != nil { return err } return nil } func (s *scenario) Run(ctx context.Context) error { // website-generator: creates about 10800 websites over 15 minutes // website-deleter: deletes about 1800 websites over 15 minutes // => in total, there will be about 9000 websites after 15 minutes if err := (&generator.Every{ Name: "website-generator", Do: func(ctx context.Context, c client.Client) error { return generator.CreateWebsite(ctx, c, generator.WithLabels(s.Labels)) }, Rate: rate.Limit(12), }).AddToManager(s.Manager); err != nil { return fmt.Errorf("error adding website-generator: %w", err) } if err := (&generator.Every{ Name: "website-deleter", Do: func(ctx context.Context, c client.Client) error { return generator.DeleteWebsite(ctx, c, s.Labels) }, Rate: rate.Limit(2), }).AddToManager(s.Manager); err != nil { return fmt.Errorf("error adding website-deleter: %w", err) } // trigger individual spec changes for website once per minute // => peaks at about 150 spec changes per second at the end of the experiment // (triggers roughly double the reconciliation rate in website controller because of deployment watches) if err := (&generator.ForEach[*webhostingv1alpha1.Website]{ Name: "website-mutator", Do: func(ctx context.Context, c client.Client, obj *webhostingv1alpha1.Website) error { return client.IgnoreNotFound(generator.MutateWebsite(ctx, c, obj, s.Labels)) }, Every: time.Minute, }).AddToManager(s.Manager); err != nil { return fmt.Errorf("error adding website-mutator: %w", err) } return s.Wait(ctx, 15*time.Minute) } ================================================ FILE: webhosting-operator/pkg/experiment/scenario/chaos/chaos.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package chaos import ( "context" "fmt" "time" "golang.org/x/time/rate" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/generator" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/scenario/base" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/utils" ) const ScenarioName = "chaos" func init() { s := &scenario{} s.Scenario = &base.Scenario{ ScenarioName: ScenarioName, Delegate: s, } experiment.RegisterScenario(s) } type scenario struct { *base.Scenario } func (s *scenario) Description() string { return "Create 4.5k websites over 15 minutes and terminate a random shard every 5 minutes" } func (s *scenario) LongDescription() string { return `The ` + ScenarioName + ` scenario generates load and chaos for the webhosting-operator: - website creation: 4500 over 15m - website spec changes: 0.5/m per object, max 37.5/s - shard termination (pod deletion): 1/m ` } func (s *scenario) Prepare(ctx context.Context) error { s.Log.Info("Preparing themes") if err := generator.CreateThemes(ctx, s.Client, 50, generator.WithLabels(s.Labels), generator.WithOwnerReference(s.OwnerRef)); err != nil { return err } s.Log.Info("Preparing projects") if err := generator.CreateProjects(ctx, s.Client, 20, generator.WithLabels(s.Labels), generator.WithOwnerReference(s.OwnerRef)); err != nil { return err } return nil } func (s *scenario) Run(ctx context.Context) error { // website-generator: creates about 4500 websites over 15 minutes if err := (&generator.Every{ Name: "website-generator", Do: func(ctx context.Context, c client.Client) error { return generator.CreateWebsite(ctx, c, generator.WithLabels(s.Labels)) }, Rate: rate.Limit(5), }).AddToManager(s.Manager); err != nil { return fmt.Errorf("error adding website-generator: %w", err) } // trigger individual spec changes for website every other minute // => peaks at about 37.5 spec changes per second at the end of the experiment // (triggers roughly double the reconciliation rate in website controller because of deployment watches) if err := (&generator.ForEach[*webhostingv1alpha1.Website]{ Name: "website-mutator", Do: func(ctx context.Context, c client.Client, obj *webhostingv1alpha1.Website) error { return client.IgnoreNotFound(generator.MutateWebsite(ctx, c, obj, s.Labels)) }, Every: 2 * time.Minute, }).AddToManager(s.Manager); err != nil { return fmt.Errorf("error adding website-mutator: %w", err) } // Terminate a random shard every 5 minutes if err := (&generator.Every{ Name: "shard-terminator", Do: terminateRandomShard, Rate: rate.Every(5 * time.Minute), }).AddToManager(s.Manager); err != nil { return fmt.Errorf("error adding shard-terminator: %w", err) } return s.Wait(ctx, 15*time.Minute) } func terminateRandomShard(ctx context.Context, c client.Client) error { log := logf.FromContext(ctx) podList := &corev1.PodList{} if err := c.List(ctx, podList, client.InNamespace(webhostingv1alpha1.NamespaceSystem), client.MatchingLabels{"app.kubernetes.io/name": webhostingv1alpha1.WebhostingOperatorName}, ); err != nil { return err } if len(podList.Items) == 0 { log.Info("No shards found, skipping termination") return nil } pod := utils.PickRandom(podList.Items) if err := c.Delete(ctx, &pod); err != nil { return err } log.Info("Terminated shard", "pod", client.ObjectKeyFromObject(&pod)) return nil } ================================================ FILE: webhosting-operator/pkg/experiment/scenario/rolling-update/rolling_update.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package rolling_update import ( "context" "fmt" "time" "golang.org/x/time/rate" appsv1 "k8s.io/api/apps/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/generator" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/scenario/base" ) const ScenarioName = "rolling-update" func init() { s := &scenario{} s.Scenario = &base.Scenario{ ScenarioName: ScenarioName, Delegate: s, } experiment.RegisterScenario(s) } type scenario struct { *base.Scenario } func (s *scenario) Description() string { return "Create 9k websites in 15 minutes while rolling the operator" } func (s *scenario) LongDescription() string { return `The ` + ScenarioName + ` scenario combines several operations typical for a lively operator environment with rolling updates: - website creation: 10800 over 15m - website deletion: 1800 over 15m - website spec changes: 1/m per object, max 150/s - rolling update of webhosting-operator: 1 every 5m ` } func (s *scenario) Prepare(ctx context.Context) error { s.Log.Info("Preparing themes") if err := generator.CreateThemes(ctx, s.Client, 50, generator.WithLabels(s.Labels), generator.WithOwnerReference(s.OwnerRef)); err != nil { return err } s.Log.Info("Preparing projects") if err := generator.CreateProjects(ctx, s.Client, 20, generator.WithLabels(s.Labels), generator.WithOwnerReference(s.OwnerRef)); err != nil { return err } return nil } func (s *scenario) Run(ctx context.Context) error { // website-generator: creates about 10800 websites over 15 minutes // website-deleter: deletes about 1800 websites over 15 minutes // => in total, there will be about 9000 websites after 15 minutes if err := (&generator.Every{ Name: "website-generator", Do: func(ctx context.Context, c client.Client) error { return generator.CreateWebsite(ctx, c, generator.WithLabels(s.Labels)) }, Rate: rate.Limit(12), }).AddToManager(s.Manager); err != nil { return fmt.Errorf("error adding website-generator: %w", err) } if err := (&generator.Every{ Name: "website-deleter", Do: func(ctx context.Context, c client.Client) error { return generator.DeleteWebsite(ctx, c, s.Labels) }, Rate: rate.Limit(2), }).AddToManager(s.Manager); err != nil { return fmt.Errorf("error adding website-deleter: %w", err) } // trigger individual spec changes for website once per minute // => peaks at about 150 spec changes per second at the end of the experiment // (triggers roughly double the reconciliation rate in website controller because of deployment watches) if err := (&generator.ForEach[*webhostingv1alpha1.Website]{ Name: "website-mutator", Do: func(ctx context.Context, c client.Client, obj *webhostingv1alpha1.Website) error { return client.IgnoreNotFound(generator.MutateWebsite(ctx, c, obj, s.Labels)) }, Every: time.Minute, }).AddToManager(s.Manager); err != nil { return fmt.Errorf("error adding website-mutator: %w", err) } // trigger a rolling update of the webhosting-operator every 5 minutes if err := (&generator.Every{ Name: "rolling-updater", Do: triggerRollingUpdate, Rate: rate.Every(5 * time.Minute), }).AddToManager(s.Manager); err != nil { return fmt.Errorf("error adding rolling-updater: %w", err) } return s.Wait(ctx, 15*time.Minute) } func triggerRollingUpdate(ctx context.Context, c client.Client) error { key := client.ObjectKey{Namespace: webhostingv1alpha1.NamespaceSystem, Name: webhostingv1alpha1.WebhostingOperatorName} var object client.Object = &appsv1.Deployment{} if err := c.Get(ctx, key, object); err != nil { if !apierrors.IsNotFound(err) { return err } object = &appsv1.StatefulSet{} if err := c.Get(ctx, key, object); err != nil { if !apierrors.IsNotFound(err) { return err } panic("neither Deployment nor StatefulSet found for webhosting-operator, aborting experiment") } } patch := client.RawPatch(types.MergePatchType, []byte(`{"spec":{"template":{"metadata":{"annotations":{"rolling-update":"`+time.Now().UTC().Format(time.RFC3339)+`"}}}}}`)) if err := c.Patch(ctx, object, patch); err != nil { return err } logf.FromContext(ctx).Info("Triggered rolling update") return nil } ================================================ FILE: webhosting-operator/pkg/experiment/scenario/scale-out/scale_out.go ================================================ /* Copyright 2024 Tim Ebert. 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. */ package scaleout import ( "context" "fmt" "time" "golang.org/x/time/rate" "sigs.k8s.io/controller-runtime/pkg/client" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/generator" "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/experiment/scenario/base" ) const ScenarioName = "scale-out" func init() { s := &scenario{} s.Scenario = &base.Scenario{ ScenarioName: ScenarioName, Delegate: s, } experiment.RegisterScenario(s) } type scenario struct { *base.Scenario } func (s *scenario) Description() string { return "Measure scale-out properties with a high churn rate" } func (s *scenario) LongDescription() string { return `The ` + ScenarioName + ` scenario is designed to overload 5 webhosting-operator instances with 5 workers within 15m: - website creation: 9000 over 15m - website spec changes: 2/m per object, max 300/s ` } func (s *scenario) Prepare(ctx context.Context) error { s.Log.Info("Preparing themes") if err := generator.CreateThemes(ctx, s.Client, 50, generator.WithLabels(s.Labels), generator.WithOwnerReference(s.OwnerRef)); err != nil { return err } s.Log.Info("Preparing projects") if err := generator.CreateProjects(ctx, s.Client, 20, generator.WithLabels(s.Labels), generator.WithOwnerReference(s.OwnerRef)); err != nil { return err } return nil } func (s *scenario) Run(ctx context.Context) error { // website-generator: creates about 9000 websites over 15 minutes if err := (&generator.Every{ Name: "website-generator", Do: func(ctx context.Context, c client.Client) error { return generator.CreateWebsite(ctx, c, generator.WithLabels(s.Labels)) }, Rate: rate.Limit(10), }).AddToManager(s.Manager); err != nil { return fmt.Errorf("error adding website-generator: %w", err) } // trigger individual spec changes for website twice per minute // => peaks at about 300 spec changes per second at the end of the experiment // (triggers roughly double the reconciliation rate in website controller because of deployment watches) if err := (&generator.ForEach[*webhostingv1alpha1.Website]{ Name: "website-mutator", Do: func(ctx context.Context, c client.Client, obj *webhostingv1alpha1.Website) error { return client.IgnoreNotFound(generator.MutateWebsite(ctx, c, obj, s.Labels)) }, Every: 30 * time.Second, Workers: 20, }).AddToManager(s.Manager); err != nil { return fmt.Errorf("error adding website-mutator: %w", err) } return s.Wait(ctx, 15*time.Minute) } ================================================ FILE: webhosting-operator/pkg/experiment/scenario.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package experiment import ( "fmt" "sort" "sigs.k8s.io/controller-runtime/pkg/manager" ) var registry = make(map[string]Scenario) // Scenario is an evaluation scenario that can be executed by experiment. type Scenario interface { // Name returns the name of the scenario. Name() string // Description returns the description of the scenario. Description() string // LongDescription returns the description of the scenario. LongDescription() string // Done is closed once the scenario is finished. Done() <-chan struct{} // AddToManager adds all runnables of the scenario to the manager. AddToManager(manager.Manager) error } // RegisterScenario registers a new scenario in the registry. func RegisterScenario(s Scenario) { if _, ok := registry[s.Name()]; ok { panic(fmt.Errorf("scenario %q already registered", s.Name())) } registry[s.Name()] = s } // GetAllScenarios returns all registered scenarios. func GetAllScenarios() []Scenario { all := make([]Scenario, 0, len(registry)) for _, s := range registry { all = append(all, s) } sort.Slice(all, func(i, j int) bool { return all[i].Name() < all[j].Name() }) return all } // GetScenario gets a single registered scenario by name. func GetScenario(s string) Scenario { return registry[s] } ================================================ FILE: webhosting-operator/pkg/experiment/tracker/tracker.go ================================================ /* Copyright 2024 Tim Ebert. 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. */ package tracker import ( "cmp" "slices" "sync" ) // tracker is a generic map that only allows manipulating keys via the set operation ("create or update"). // It synchronizes access to the map itself, but not to the contained values. Values need to synchronize concurrent // access on their own. // This is done to efficiently store multi-level tracking information in a concurrency safe way. type tracker[K cmp.Ordered, V any] struct { lock sync.RWMutex values map[K]*V new func() *V } // sortedValues returns a slice of values in the tracker's map sorted by their respective keys. func (t *tracker[K, V]) sortedValues() []*V { t.lock.RLock() defer t.lock.RUnlock() keys := make([]K, 0, len(t.values)) for k := range t.values { keys = append(keys, k) } slices.Sort(keys) values := make([]*V, 0, len(t.values)) for _, k := range keys { values = append(values, t.values[k]) } return values } // set adds a new key to the map and runs mutate on its value, or mutates the value of an existing key. func (t *tracker[K, V]) set(key K, mutate func(v *V)) { // fast path for existing keys t.lock.RLock() if v, ok := t.values[key]; ok { defer t.lock.RUnlock() mutate(v) return } // slow path for new keys // upgrade lock for adding new keys t.lock.RUnlock() t.lock.Lock() defer t.lock.Unlock() // re-check for concurrent additions if v, ok := t.values[key]; ok { mutate(v) return } // add new key var v *V if t.new != nil { v = t.new() } else { v = new(V) } t.values[key] = v mutate(v) } ================================================ FILE: webhosting-operator/pkg/experiment/tracker/website.go ================================================ /* Copyright 2024 Tim Ebert. 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. */ package tracker import ( "context" "sync" "time" "github.com/go-logr/logr" "github.com/prometheus/client_golang/prometheus" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/workqueue" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/metrics" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" ) var ( // NOTE: upper bound 5 is the SLO. Align buckets with SLO so that when p99 estimation grows above SLO we are sure // that p99 is actually above SLO. // See https://prometheus.io/docs/practices/histograms/#errors-of-quantile-estimation buckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} websiteReconciliationLatency = prometheus.NewHistogramVec(prometheus.HistogramOpts{ Namespace: "experiment", Subsystem: "website", Name: "reconciliation_duration_seconds", Help: "Latency from Website creation or spec update until the generation is observed as ready by a watch. " + "This is an SLI for controller performance.", Buckets: buckets, }, nil) websiteBackfilledGenerations = prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: "experiment", Subsystem: "website", Name: "backfilled_generations_total", Help: "Counter for Website generations that were never observed as ready before the next generation appeared. " + "For such generations, the time when the next generation got ready is used for calculating the reconciliation latency. " + "This metric serves as an indicator for how accurate the reconciliation latency measurement is.", }, nil) watchLatency = prometheus.NewHistogramVec(prometheus.HistogramOpts{ Namespace: "experiment", Name: "watch_latency_seconds", Help: "Latency from Website transition time until observed by a watch event in experiment. " + "This metric serves as an indicator for how experiment itself is performing to ensure accurate measurements.", Buckets: buckets, }, nil) ) // WebsiteTracker tracks how long it takes for generations of Website objects to be reconciled and get ready. type WebsiteTracker struct { reader client.Reader // objects maps an object's UID to the object's generation information. // The UID is used as the key instead of a namespaced name so that the tracker can distinguish between object // instances with the same namespaced name. objects *tracker[types.UID, objectGenerations] } // objectGenerations stores information about all generations of a single object. type objectGenerations struct { lock sync.Mutex generations *tracker[int64, generationTimes] } // generationTimes stores information about a single generation of an object. // It doesn't synchronize access. Access is synchronized by the lock on objectGenerations level. type generationTimes struct { created, ready time.Time recorded bool } func newObjectsTracker() *tracker[types.UID, objectGenerations] { return &tracker[types.UID, objectGenerations]{ values: map[types.UID]*objectGenerations{}, new: func() *objectGenerations { return &objectGenerations{ generations: newGenerationsTracker(), } }, } } func newGenerationsTracker() *tracker[int64, generationTimes] { return &tracker[int64, generationTimes]{ values: map[int64]*generationTimes{}, } } // AddToManager initializes the tracker, registers its metrics, and starts watching objects. func (w *WebsiteTracker) AddToManager(mgr manager.Manager) error { if w.reader == nil { w.reader = mgr.GetCache() } w.objects = newObjectsTracker() // initialize counters websiteBackfilledGenerations.WithLabelValues().Add(0) // register all metrics metrics.Registry.MustRegister(websiteReconciliationLatency, websiteBackfilledGenerations, watchLatency) return builder.ControllerManagedBy(mgr). Named("website-tracker"). Watches(&webhostingv1alpha1.Website{}, w.websiteHandler(), builder.WithPredicates(w.observedNewReadyGeneration())). WithOptions(controller.Options{ MaxConcurrentReconciles: 5, }). Complete(w) } // websiteHandler enqueues the object's UID for update requests. // It concurrently adds the observed status to the tracker and enqueues the object for reconciliation with a short delay // to give the tracker enough time to store the observed status. // This reduces the number of requeues we need to do for waiting for the ready timestamp to arrive in the tracker. func (w *WebsiteTracker) websiteHandler() handler.EventHandler { return handler.Funcs{ UpdateFunc: func(_ context.Context, e event.UpdateEvent, q workqueue.TypedRateLimitingInterface[reconcile.Request]) { website, ok := e.ObjectNew.(*webhostingv1alpha1.Website) if !ok { return } w.recordStatusGeneration(website) q.AddAfter(reconcile.Request{NamespacedName: types.NamespacedName{ Name: string(website.UID), }}, time.Second) }, } } // observedNewReadyGeneration returns a predicate that triggers when a new generation is observed to be ready and its // reconciliation latency should be recorded by the reconciler. func (w *WebsiteTracker) observedNewReadyGeneration() predicate.Predicate { return predicate.Funcs{ CreateFunc: func(_ event.CreateEvent) bool { return false }, UpdateFunc: func(e event.UpdateEvent) bool { oldWebsite, ok := e.ObjectOld.(*webhostingv1alpha1.Website) if !ok { return false } website, ok := e.ObjectNew.(*webhostingv1alpha1.Website) if !ok { return false } // Record how long it took experiment to observe the transition. if t := website.Status.LastTransitionTime; t != nil && !t.Equal(oldWebsite.Status.LastTransitionTime) { watchLatency.WithLabelValues().Observe(time.Since(t.Time).Seconds()) } // if the status changed and the website is ready, we observed a new generation becoming ready return !apiequality.Semantic.DeepEqual(oldWebsite.Status, website.Status) && website.Status.Phase == webhostingv1alpha1.PhaseReady }, DeleteFunc: func(_ event.DeleteEvent) bool { return false }, GenericFunc: func(_ event.GenericEvent) bool { return false }, } } // RecordSpecChange records a new generation of the given website as created or updated by the experiment. // Supposed to be called by the load generator. func (w *WebsiteTracker) RecordSpecChange(website *webhostingv1alpha1.Website) { // record time first, before locking t := time.Now() // store time concurrently, so that we don't block the load generator go w.objects.set(website.UID, func(generations *objectGenerations) { generations.setGenerationCreated(website.Generation, t) }) } // recordStatusGeneration records a new observed generation of the given website if it is ready. // Supposed to be called by the watch handler (synchronously). func (w *WebsiteTracker) recordStatusGeneration(website *webhostingv1alpha1.Website) { // record time first, before locking t := time.Now() // store time concurrently, so that we don't block the watch handler/reflector go w.objects.set(website.UID, func(generations *objectGenerations) { generations.setGenerationReady(website.Status.ObservedGeneration, t) }) } // setGenerationCreated records the time when the given generation was created, i.e., when the creation / spec change // happened. func (o *objectGenerations) setGenerationCreated(generation int64, t time.Time) { o.lock.Lock() defer o.lock.Unlock() o.generations.set(generation, func(times *generationTimes) { if !times.created.IsZero() { // generation was already recorded return } times.created = t }) } // setGenerationReady records the time when the given generation was observed as ready. func (o *objectGenerations) setGenerationReady(generation int64, t time.Time) { o.lock.Lock() defer o.lock.Unlock() o.generations.set(generation, func(times *generationTimes) { if !times.ready.IsZero() { // generation was already recorded return } times.ready = t }) } // Reconcile iterates over all objects and records metrics for the generations that were observed to be ready. func (w *WebsiteTracker) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) { log := logf.FromContext(ctx) uid := types.UID(req.Name) var res reconcile.Result w.objects.set(uid, func(generations *objectGenerations) { res = generations.reconcile(log) }) return res, nil } // reconcile iterates over the object's generations and records newly observed finished reconciliations in the latency // metric. func (o *objectGenerations) reconcile(log logr.Logger) reconcile.Result { o.lock.Lock() defer o.lock.Unlock() generations := generationsList(o.generations.sortedValues()) generations.backfillGenerations() if finished := generations.recordNewReadyGenerations(log); !finished { return reconcile.Result{Requeue: true} } return reconcile.Result{} } type generationsList []*generationTimes // backfillGenerations backfills the ready time for generations if we observed a newer ready generation. // This might be necessary if we missed some watch events, or multiple generations were created in quick succession // where only a later one was reconciled by the controller to be ready. // The generations slice must be sorted by generation in ascending order. func (gg generationsList) backfillGenerations() { var newerReadyTime time.Time for i := len(gg) - 1; i >= 0; i-- { g := gg[i] if g.recorded { continue } if g.ready.IsZero() { // this generation was not observed as ready, // copy the ready time from the generation after it (if it has been observed as ready) g.ready = newerReadyTime websiteBackfilledGenerations.WithLabelValues().Add(1) } else { // this generation was observed as ready, copy the timestamp for backfilling earlier generations. newerReadyTime = g.ready } } } // recordNewReadyGenerations records all newly observed ready generations. // Returns true if all generations have been recorded, false if there are unready generations left. func (gg generationsList) recordNewReadyGenerations(log logr.Logger) bool { finished := true for _, g := range gg { if g.recorded { continue } if g.created.IsZero() || g.ready.IsZero() { finished = false continue } latency := g.ready.Sub(g.created) logLevel := 1 if latency > 30*time.Second { logLevel = 0 } log.V(logLevel).Info("Observed ready website", "latency", latency, "created", g.created, "ready", g.ready) websiteReconciliationLatency.WithLabelValues().Observe(latency.Seconds()) g.recorded = true } return finished } ================================================ FILE: webhosting-operator/pkg/metrics/add.go ================================================ /* Copyright 2024 Tim Ebert. 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. */ package metrics import ( "fmt" "sigs.k8s.io/controller-runtime/pkg/manager" ) const namespace = "kube" // AddToManager adds all metrics exporters for webhosting objects to the manager. func AddToManager(mgr manager.Manager) error { if err := WebsiteExporter.AddToManager(mgr); err != nil { return fmt.Errorf("failed to add website exporter: %w", err) } if err := ThemeExporter.AddToManager(mgr); err != nil { return fmt.Errorf("failed to add theme exporter: %w", err) } return nil } ================================================ FILE: webhosting-operator/pkg/metrics/theme.go ================================================ /* Copyright 2024 Tim Ebert. 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. */ package metrics import ( "github.com/prometheus/client_golang/prometheus" "github.com/timebertt/kubernetes-controller-sharding/pkg/metrics/exporter" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" ) var ThemeExporter = exporter.Exporter[*webhostingv1alpha1.Theme, *webhostingv1alpha1.ThemeList]{ Namespace: namespace, Subsystem: "theme", StaticLabelKeys: []string{"theme", "uid"}, GenerateStaticLabelValues: func(theme *webhostingv1alpha1.Theme) []string { return []string{theme.Name, string(theme.UID)} }, Metrics: []exporter.Metric[*webhostingv1alpha1.Theme]{ { Name: "info", Help: "Information about a Theme", LabelKeys: []string{"color", "font_family"}, Generate: func(desc *prometheus.Desc, theme *webhostingv1alpha1.Theme, staticLabelValues []string, ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( desc, prometheus.GaugeValue, 1, append(staticLabelValues, theme.Spec.Color, theme.Spec.FontFamily)..., ) }, }, { Name: "metadata_generation", Help: "The generation of a Theme", Generate: func(desc *prometheus.Desc, theme *webhostingv1alpha1.Theme, staticLabelValues []string, ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( desc, prometheus.GaugeValue, float64(theme.Generation), staticLabelValues..., ) }, }, }, } ================================================ FILE: webhosting-operator/pkg/metrics/website.go ================================================ /* Copyright 2024 Tim Ebert. 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. */ package metrics import ( "github.com/prometheus/client_golang/prometheus" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/metrics/exporter" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" ) var WebsiteExporter = exporter.Exporter[*webhostingv1alpha1.Website, *webhostingv1alpha1.WebsiteList]{ Namespace: namespace, Subsystem: "website", StaticLabelKeys: []string{"namespace", "website", "uid"}, GenerateStaticLabelValues: func(website *webhostingv1alpha1.Website) []string { return []string{website.Namespace, website.Name, string(website.UID)} }, Metrics: []exporter.Metric[*webhostingv1alpha1.Website]{ { Name: "info", Help: "Information about a Website", LabelKeys: []string{"theme"}, Generate: func(desc *prometheus.Desc, website *webhostingv1alpha1.Website, staticLabelValues []string, ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( desc, prometheus.GaugeValue, 1, append(staticLabelValues, website.Spec.Theme)..., ) }, }, { Name: "shard", Help: "Sharding information about a Website", LabelKeys: []string{"shard", "drain"}, Generate: func(desc *prometheus.Desc, website *webhostingv1alpha1.Website, staticLabelValues []string, ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( desc, prometheus.GaugeValue, 1, append(staticLabelValues, website.Labels[shardingv1alpha1.LabelShard(webhostingv1alpha1.WebhostingOperatorName)], website.Labels[shardingv1alpha1.LabelDrain(webhostingv1alpha1.WebhostingOperatorName)], )..., ) }, }, { Name: "metadata_generation", Help: "The generation of a Website", Generate: func(desc *prometheus.Desc, website *webhostingv1alpha1.Website, staticLabelValues []string, ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( desc, prometheus.GaugeValue, float64(website.Generation), staticLabelValues..., ) }, }, { Name: "observed_generation", Help: "The latest generation observed by the Website controller", Generate: func(desc *prometheus.Desc, website *webhostingv1alpha1.Website, staticLabelValues []string, ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( desc, prometheus.GaugeValue, float64(website.Status.ObservedGeneration), staticLabelValues..., ) }, }, { Name: "status_phase", Help: "The Website's current phase (StateSet)", LabelKeys: []string{"phase"}, Generate: exporter.GenerateStateSet[*webhostingv1alpha1.Website]( exporter.KnownStates(webhostingv1alpha1.AllWebsitePhases), nil, func(website *webhostingv1alpha1.Website) string { return string(website.Status.Phase) }, ), }, }, } ================================================ FILE: webhosting-operator/pkg/utils/kubernetes.go ================================================ /* Copyright 2023 Tim Ebert. 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. */ package utils import ( "os" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" ) // RunningInCluster implements a heuristic for determining whether the process is running in a cluster or not. func RunningInCluster() bool { _, err := os.Stat("/var/run/secrets/kubernetes.io/serviceaccount/namespace") if err == nil { return true } return os.Getenv("KUBERNETES_SERVICE_HOST") != "" } // IsDeploymentReady returns true if the current generation has been observed by the deployment controller and has been // fully rolled out. func IsDeploymentReady(deployment *appsv1.Deployment) bool { if deployment.Status.ObservedGeneration < deployment.Generation { return false } available := GetDeploymentCondition(deployment.Status.Conditions, appsv1.DeploymentAvailable) if available == nil || available.Status != corev1.ConditionTrue { return false } progressing := GetDeploymentCondition(deployment.Status.Conditions, appsv1.DeploymentProgressing) if progressing == nil || progressing.Status != corev1.ConditionTrue || progressing.Reason != "NewReplicaSetAvailable" { // only if Progressing is in status True with reason NewReplicaSetAvailable, the Deployment has been fully rolled out // note: old pods or excess pods (scale-down) might still be terminating, but there is no way to tell this from the // Deployment's status, see https://github.com/kubernetes/kubernetes/issues/110171 return false } return true } // GetDeploymentCondition returns the condition with the given type or nil, if it is not included. func GetDeploymentCondition(conditions []appsv1.DeploymentCondition, conditionType appsv1.DeploymentConditionType) *appsv1.DeploymentCondition { for _, cond := range conditions { if cond.Type == conditionType { return &cond } } return nil } ================================================ FILE: webhosting-operator/pkg/utils/utils.go ================================================ /* Copyright 2022 Tim Ebert. 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. */ package utils import ( "math/rand" ) // PickRandom picks a random element from the given slice. func PickRandom[T any](in []T) T { // nolint:gosec // doesn't need to be cryptographically secure return in[rand.Intn(len(in))] } // RandomName generates a random string with n characters that can be used as part of API object names. func RandomName(n int) string { const charset = "abcdefghijklmnopqrstuvwxyz" result := make([]byte, n) for i := range result { // nolint:gosec // doesn't need to be cryptographically secure result[i] = charset[rand.Intn(len(charset))] } return string(result) } ================================================ FILE: webhosting-operator/test/e2e/e2e_suite_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package e2e import ( "context" "flag" "maps" "testing" "time" "github.com/go-logr/logr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/envtest/komega" "sigs.k8s.io/controller-runtime/pkg/log/zap" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" ) var skipCleanup bool func TestMain(m *testing.M) { flag.BoolVar(&skipCleanup, "skip-cleanup", false, "Skip cleanup after test failure") flag.Parse() m.Run() } func TestE2E(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Webhosting Operator E2E Test Suite") } const ( testID = "e2e-webhosting-operator" ShortTimeout = 10 * time.Second MediumTimeout = time.Minute ) var ( log logr.Logger testClient client.Client testRunID string testRunLabels map[string]string ) var _ = BeforeSuite(func() { log = zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter)).WithName(testID) restConfig, err := config.GetConfig() Expect(err).NotTo(HaveOccurred()) scheme := runtime.NewScheme() schemeBuilder := runtime.NewSchemeBuilder( clientgoscheme.AddToScheme, shardingv1alpha1.AddToScheme, webhostingv1alpha1.AddToScheme, ) Expect(schemeBuilder.AddToScheme(scheme)).To(Succeed()) testClient, err = client.New(restConfig, client.Options{Scheme: scheme}) Expect(err).NotTo(HaveOccurred()) clientContext, clientCancel := context.WithCancel(context.Background()) komega.SetClient(testClient) komega.SetContext(clientContext) DeferCleanup(clientCancel) testRunID = testID + "-" + test.RandomSuffix() testRunLabels = map[string]string{ testID: testRunID, } log = log.WithValues("testRun", testRunID) }) var ( controllerRing *shardingv1alpha1.ControllerRing namespace *corev1.Namespace controllerDeployment *appsv1.Deployment ) var _ = BeforeEach(func(ctx SpecContext) { By("Set up test Namespace") namespace = &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{ GenerateName: testRunID + "-", Labels: maps.Clone(testRunLabels), }} namespace.Labels[webhostingv1alpha1.LabelKeyProject] = webhostingv1alpha1.LabelValueProject // We create a dedicated test namespace and clean it up for every test case to ensure a clean test environment. Expect(testClient.Create(ctx, namespace)).To(Succeed()) log.Info("Created test Namespace", "namespace", namespace.Name) DeferCleanup(func(ctx SpecContext) { if ctx.SpecReport().Failed() && skipCleanup { Skip("Leaving state of test failure because --skip-cleanup is set to true") } By("Delete all Websites in test Namespace") Expect(testClient.DeleteAllOf(ctx, &webhostingv1alpha1.Website{}, client.InNamespace(namespace.Name))).To(Succeed()) By("Delete test Namespace") Eventually(ctx, func() error { return testClient.Delete(ctx, namespace) }).Should(Or(Succeed(), BeNotFoundError())) }, NodeTimeout(MediumTimeout)) By("Set up test ControllerRing") controllerRing = &shardingv1alpha1.ControllerRing{ObjectMeta: metav1.ObjectMeta{Name: webhostingv1alpha1.WebhostingOperatorName}} By("Scaling webhosting-operator") controllerDeployment = &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: webhostingv1alpha1.WebhostingOperatorName, Namespace: webhostingv1alpha1.NamespaceSystem}} scaleController(ctx, 3) DeferCleanup(func(ctx SpecContext) { if ctx.SpecReport().Failed() && skipCleanup { Skip("Leaving state of test failure because --skip-cleanup is set to true") } By("Scaling webhosting-operator") scaleController(ctx, 3) }, NodeTimeout(ShortTimeout)) By("Set up test Theme") theme = &webhostingv1alpha1.Theme{ ObjectMeta: metav1.ObjectMeta{ Name: namespace.Name, Labels: maps.Clone(testRunLabels), }, Spec: webhostingv1alpha1.ThemeSpec{ Color: "cyan", FontFamily: "arial", }, } Expect(controllerutil.SetOwnerReference(namespace, theme, testClient.Scheme(), controllerutil.WithBlockOwnerDeletion(true))).To(Succeed()) Expect(testClient.Create(ctx, theme)).To(Succeed()) }, NodeTimeout(MediumTimeout), OncePerOrdered) ================================================ FILE: webhosting-operator/test/e2e/webhosting_operator_test.go ================================================ /* Copyright 2025 Tim Ebert. 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. */ package e2e import ( "context" "fmt" "maps" "strconv" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" appsv1 "k8s.io/api/apps/v1" autoscalingv1 "k8s.io/api/autoscaling/v1" coordinationv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/sets" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/apiutil" . "sigs.k8s.io/controller-runtime/pkg/envtest/komega" shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1" "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/leases" "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test" . "github.com/timebertt/kubernetes-controller-sharding/pkg/utils/test/matchers" webhostingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/webhosting-operator/pkg/apis/webhosting/v1alpha1" ) const objectCount = 100 var ( mainObject = &webhostingv1alpha1.Website{} controlledObjects = []client.Object{ &appsv1.Deployment{}, &corev1.ConfigMap{}, &corev1.Service{}, &networkingv1.Ingress{}, } ) var theme *webhostingv1alpha1.Theme var _ = Describe("Webhosting Operator", Label(webhostingv1alpha1.WebhostingOperatorName), func() { Describe("setup", Ordered, func() { itDeploymentShouldBeAvailable(3) itControllerRingShouldHaveAvailableShards(3) itShouldRecognizeReadyShardLeases(3) }) Describe("creating a website", Ordered, func() { var ( website *webhostingv1alpha1.Website shard string ) itControllerRingShouldHaveAvailableShards(3) itShouldRecognizeReadyShardLeases(3) It("should assign the main object to a healthy shard", func(ctx SpecContext) { // Verify that the sharder successfully injects the shard label. // The webhook has failurePolicy=Ignore, so we might need to retry the creation until the injection succeeds. Eventually(ctx, func(g Gomega) *webhostingv1alpha1.Website { website = newWebsite("foo-" + test.RandomSuffix()) g.Expect(testClient.Create(ctx, website)).To(Succeed()) return website }).Should(And( HaveLabelWithValue(controllerRing.LabelShard(), BeElementOf(shards)), Not(HaveLabel(controllerRing.LabelDrain())), )) shard = website.Labels[controllerRing.LabelShard()] log.Info("Created object", "website", client.ObjectKeyFromObject(website), "shard", shard) }, SpecTimeout(MediumTimeout)) for _, obj := range controlledObjects { It(fmt.Sprintf("should assign the controlled %T to the same shard", obj), func(ctx SpecContext) { Eventually(ctx, ObjectList(listOf(obj), client.InNamespace(namespace.Name), client.MatchingLabels{"website": website.Name})). Should(HaveField("Items", ConsistOf(And( HaveLabelWithValue(controllerRing.LabelShard(), Equal(shard)), Not(HaveLabel(controllerRing.LabelDrain())), )))) }, SpecTimeout(MediumTimeout)) } itWebsitesShouldBeReady() }) describeScaleController("adding a shard", 4) describeScaleController("removing a shard", 2) }) func describeScaleController(text string, replicas int32) { Describe(text, Ordered, func() { itControllerRingShouldHaveAvailableShards(3) itShouldRecognizeReadyShardLeases(3) itCreateWebsites() itShouldAssignObjectsToAvailableShards() itWebsitesShouldBeReady() itScaleController(replicas) itDeploymentShouldBeAvailable(replicas) itControllerRingShouldHaveAvailableShards(replicas) itShouldRecognizeReadyShardLeases(int(replicas)) itShouldAssignObjectsToAvailableShards() itWebsitesShouldBeReady() }) } func newWebsite(name string) *webhostingv1alpha1.Website { labels := maps.Clone(testRunLabels) labels[webhostingv1alpha1.LabelKeySkipWorkload] = "true" return &webhostingv1alpha1.Website{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace.Name, Labels: labels, }, Spec: webhostingv1alpha1.WebsiteSpec{ Theme: theme.Name, }, } } func itDeploymentShouldBeAvailable(expectedReplicas int32) { GinkgoHelper() It(fmt.Sprintf("the %s Deployment should be available", webhostingv1alpha1.WebhostingOperatorName), func(ctx SpecContext) { Eventually(ctx, Object(controllerDeployment)).Should(And( HaveField("Spec.Replicas", HaveValue(BeEquivalentTo(expectedReplicas))), HaveField("Status.Replicas", BeEquivalentTo(expectedReplicas)), HaveField("Status.AvailableReplicas", BeEquivalentTo(expectedReplicas)), )) }, SpecTimeout(MediumTimeout)) } func itControllerRingShouldHaveAvailableShards(expectedAvailableShards int32) { GinkgoHelper() It(fmt.Sprintf("the ControllerRing should be ready and should have %d available shards", expectedAvailableShards), func(ctx SpecContext) { Eventually(ctx, Object(controllerRing)).Should(And( HaveField("Status.AvailableShards", BeEquivalentTo(expectedAvailableShards)), HaveField("Status.Conditions", ConsistOf( MatchCondition( OfType(shardingv1alpha1.ControllerRingReady), WithStatus(metav1.ConditionTrue), ), )), )) }, SpecTimeout(MediumTimeout)) } var shards []string func itShouldRecognizeReadyShardLeases(expectedCount int) { GinkgoHelper() It(fmt.Sprintf("should recognize %d ready shard leases", expectedCount), func(ctx SpecContext) { leaseList := &coordinationv1.LeaseList{} Eventually(ctx, ObjectList(leaseList, client.InNamespace(controllerDeployment.Namespace), client.MatchingLabels{ shardingv1alpha1.LabelControllerRing: controllerRing.Name, shardingv1alpha1.LabelState: leases.Ready.String(), })).Should(HaveField("Items", HaveLen(expectedCount))) shards = make([]string, len(leaseList.Items)) for i, lease := range leaseList.Items { shards[i] = lease.Name } }, SpecTimeout(ShortTimeout)) } func itCreateWebsites() { GinkgoHelper() It(fmt.Sprintf("create %d websites", objectCount), func(ctx SpecContext) { for i := 0; i < objectCount; i++ { website := newWebsite("foo-" + strconv.Itoa(i)) Expect(testClient.Create(ctx, website)).To(Succeed(), "should create website %s", website.Name) } }, SpecTimeout(MediumTimeout)) } func itWebsitesShouldBeReady() { GinkgoHelper() It("all Websites should be ready", func(ctx SpecContext) { Eventually(ctx, ObjectList(&webhostingv1alpha1.WebsiteList{}, client.InNamespace(namespace.Name))).Should( HaveField("Items", HaveEach( HaveField("Status.Phase", webhostingv1alpha1.PhaseReady), )), ) }, SpecTimeout(MediumTimeout)) } func itScaleController(replicas int32) { GinkgoHelper() It(fmt.Sprintf("scale the controller to %d replicas", replicas), func(ctx SpecContext) { scaleController(ctx, replicas) }, NodeTimeout(ShortTimeout)) } func scaleController(ctx context.Context, replicas int32) { GinkgoHelper() patch := client.MergeFrom(&autoscalingv1.Scale{}) scale := &autoscalingv1.Scale{Spec: autoscalingv1.ScaleSpec{Replicas: replicas}} Expect(testClient.SubResource("scale").Patch(ctx, controllerDeployment, patch, client.WithSubResourceBody(scale), &client.SubResourcePatchOptions{})).To(Succeed()) log.Info("Scaled controller", "replicas", replicas) } func itShouldAssignObjectsToAvailableShards() { GinkgoHelper() for _, obj := range append([]client.Object{mainObject}, controlledObjects...) { It(fmt.Sprintf("should assign the %Ts to the available shards", obj), func(ctx SpecContext) { eventuallyShouldAssignObjectsToAvailableShards(ctx, obj) }, NodeTimeout(MediumTimeout)) } } func eventuallyShouldAssignObjectsToAvailableShards(ctx context.Context, obj client.Object) { GinkgoHelper() Eventually(ctx, func(g Gomega) { list := listOf(obj) g.Expect(ObjectList(list, client.InNamespace(namespace.Name), client.MatchingLabels(testRunLabels))()).To(HaveField("Items", HaveLen(objectCount))) usedShards := sets.New[string]() Expect(meta.EachListItem(list, func(obj runtime.Object) error { g.Expect(obj).To(HaveLabelWithValue(controllerRing.LabelShard(), Not(BeEmpty())), "object %T %s should be assigned") g.Expect(obj).NotTo(HaveLabel(controllerRing.LabelDrain()), "object %T %s should not have drain label") usedShards.Insert(obj.(client.Object).GetLabels()[controllerRing.LabelShard()]) return nil })).To(Succeed()) g.Expect(usedShards.UnsortedList()).To(ConsistOf(shards), "should use all available shards") }).Should(Succeed()) } func listOf(obj client.Object) client.ObjectList { gvk, err := apiutil.GVKForObject(obj, testClient.Scheme()) Expect(err).NotTo(HaveOccurred()) gvk.Kind += "List" list, err := testClient.Scheme().New(gvk) Expect(err).NotTo(HaveOccurred()) return list.(client.ObjectList) }