From 835025aad4f95fcb12e27bac9b6b59f72f4def7e Mon Sep 17 00:00:00 2001 From: Thuan Vo Date: Wed, 29 May 2024 14:38:55 -0700 Subject: [PATCH] feat(discovery): configurations for KubeAPI discovery (#128) * feat(discovery): configurations for KubeAPI discovery * feat(values): add default values for namespace and port configs * feat(rbac): update rbac resources to support multinamespaces * fix(rbac): fix newline trimmed causing invalid rolebinding set * chore(rbac): rename templates * chore(rbac): rbac should only be generated when necessary * fix(deploy): pre-process config lists * chore(deploy): rename env var * feat(discovery): use flags to disable default discovery options * fix(rbac): copy roles instead of clusterrole * fix(rbac): should generate roles & rolebinding for install namespace if not disabled * fix(rbac): handle null case * chore(template): fix typos --- charts/cryostat/README.md | 58 ++++++++------ charts/cryostat/templates/_helpers.tpl | 13 ++++ charts/cryostat/templates/deployment.yaml | 12 +++ charts/cryostat/templates/role.yaml | 26 ++++++- charts/cryostat/templates/rolebinding.yaml | 19 ++++- charts/cryostat/values.schema.json | 88 +++++++++++++++++----- charts/cryostat/values.yaml | 17 +++++ 7 files changed, 184 insertions(+), 49 deletions(-) diff --git a/charts/cryostat/README.md b/charts/cryostat/README.md index 11a4a8d3..8c7801c1 100644 --- a/charts/cryostat/README.md +++ b/charts/cryostat/README.md @@ -5,31 +5,39 @@ A Helm chart for deploying [Cryostat](https://cryostat.io/) on Kubernetes and Op ### Cryostat Container -| Name | Description | Value | -| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | -| `core` | Configuration for the core Cryostat application | | -| `core.image.repository` | Repository for the main Cryostat container image | `quay.io/cryostat/cryostat` | -| `core.image.pullPolicy` | Image pull policy for the main Cryostat container image | `Always` | -| `core.image.tag` | Tag for the main Cryostat container image | `3.0.0-snapshot` | -| `core.service.type` | Type of Service to create for the Cryostat application | `ClusterIP` | -| `core.service.httpPort` | Port number to expose on the Service for Cryostat's HTTP server | `8181` | -| `core.sslProxied` | Enables SSL Proxied Environment Variables, useful when you are offloading SSL/TLS at External Loadbalancer instead of Ingress | `false` | -| `core.ingress.enabled` | Whether to create an Ingress object for the Cryostat service | `false` | -| `core.ingress.className` | Ingress class name for the Cryostat application Ingress | `""` | -| `core.ingress.annotations` | Annotations to apply to the Cryostat application Ingress | `{}` | -| `core.ingress.hosts` | Hosts to create rules for in the Cryostat application Ingress. See: [IngressSpec](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec) | `[]` | -| `core.ingress.tls` | TLS configuration for the Cryostat application Ingress. See: [IngressSpec](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec) | `[]` | -| `core.route.enabled` | Whether to create a Route object for the Cryostat service. Available only on OpenShift | `false` | -| `core.route.tls.enabled` | Whether to secure the Cryostat application Route with TLS. See: [TLSConfig](https://docs.openshift.com/container-platform/4.10/rest_api/network_apis/route-route-openshift-io-v1.html#spec-tls) | `true` | -| `core.route.tls.termination` | Type of TLS termination to use for the Cryostat application Route. One of: `edge`, `passthrough`, `reencrypt` | `edge` | -| `core.route.tls.insecureEdgeTerminationPolicy` | Specify how to handle insecure traffic for the Cryostat application Route. One of: `Allow`, `Disable`, `Redirect` | `Redirect` | -| `core.route.tls.key` | Custom private key to use when securing the Cryostat application Route | `""` | -| `core.route.tls.certificate` | Custom certificate to use when securing the Cryostat application Route | `""` | -| `core.route.tls.caCertificate` | Custom CA certificate to use, if needed to complete the certificate chain, when securing the Cryostat application Route | `""` | -| `core.route.tls.destinationCACertificate` | Provides the contents of the CA certificate of the final destination when using reencrypt termination for the Cryostat application Route | `""` | -| `core.resources` | Resource requests/limits for the Cryostat container. See: [ResourceRequirements](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#resources) | `{}` | -| `core.securityContext` | Security Context for the Cryostat container. Defaults to meet "restricted" [Pod Security Standard](https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted). See: [SecurityContext](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context-1) | `{}` | -| `core.databaseSecretName` | Name of the secret to extract password for credentials database. | `""` | +| Name | Description | Value | +| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | +| `core` | Configuration for the core Cryostat application | | +| `core.image.repository` | Repository for the main Cryostat container image | `quay.io/cryostat/cryostat` | +| `core.image.pullPolicy` | Image pull policy for the main Cryostat container image | `Always` | +| `core.image.tag` | Tag for the main Cryostat container image | `3.0.0-snapshot` | +| `core.service.type` | Type of Service to create for the Cryostat application | `ClusterIP` | +| `core.service.httpPort` | Port number to expose on the Service for Cryostat's HTTP server | `8181` | +| `core.sslProxied` | Enables SSL Proxied Environment Variables, useful when you are offloading SSL/TLS at External Loadbalancer instead of Ingress | `false` | +| `core.ingress.enabled` | Whether to create an Ingress object for the Cryostat service | `false` | +| `core.ingress.className` | Ingress class name for the Cryostat application Ingress | `""` | +| `core.ingress.annotations` | Annotations to apply to the Cryostat application Ingress | `{}` | +| `core.ingress.hosts` | Hosts to create rules for in the Cryostat application Ingress. See: [IngressSpec](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec) | `[]` | +| `core.ingress.tls` | TLS configuration for the Cryostat application Ingress. See: [IngressSpec](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec) | `[]` | +| `core.route.enabled` | Whether to create a Route object for the Cryostat service. Available only on OpenShift | `false` | +| `core.route.tls.enabled` | Whether to secure the Cryostat application Route with TLS. See: [TLSConfig](https://docs.openshift.com/container-platform/4.10/rest_api/network_apis/route-route-openshift-io-v1.html#spec-tls) | `true` | +| `core.route.tls.termination` | Type of TLS termination to use for the Cryostat application Route. One of: `edge`, `passthrough`, `reencrypt` | `edge` | +| `core.route.tls.insecureEdgeTerminationPolicy` | Specify how to handle insecure traffic for the Cryostat application Route. One of: `Allow`, `Disable`, `Redirect` | `Redirect` | +| `core.route.tls.key` | Custom private key to use when securing the Cryostat application Route | `""` | +| `core.route.tls.certificate` | Custom certificate to use when securing the Cryostat application Route | `""` | +| `core.route.tls.caCertificate` | Custom CA certificate to use, if needed to complete the certificate chain, when securing the Cryostat application Route | `""` | +| `core.route.tls.destinationCACertificate` | Provides the contents of the CA certificate of the final destination when using reencrypt termination for the Cryostat application Route | `""` | +| `core.resources` | Resource requests/limits for the Cryostat container. See: [ResourceRequirements](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#resources) | `{}` | +| `core.securityContext` | Security Context for the Cryostat container. Defaults to meet "restricted" [Pod Security Standard](https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted). See: [SecurityContext](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context-1) | `{}` | +| `core.databaseSecretName` | Name of the secret to extract password for credentials database. | `""` | +| `core.discovery` | Configuration options to the Cryostat application's target discovery mechanisms | | +| `core.discovery.kubernetes.enabled` | Enables Kubernetes API discovery mechanism | `true` | +| `core.discovery.kubernetes.installNamespaceDisabled` | When false and `namespaces` is empty, the Cryostat application will default to discovery targets in the install namespace (i.e. `{{ .Release.Namespace }}`) | `false` | +| `core.discovery.kubernetes.namespaces` | List of namespaces whose workloads the Cryostat application should be permitted to access and profile | `[]` | +| `core.discovery.kubernetes.builtInPortNamesDisabled` | When false and `portNames` is empty, the Cryostat application will use the default port name `jfr-jmx` to look for JMX connectable targets. | `false` | +| `core.discovery.kubernetes.portNames` | List of port names that the Cryostat application should look for in order to consider a target as JMX connectable | `[]` | +| `core.discovery.kubernetes.builtInPortNumbersDisabled` | When false and `portNumbers` is empty, the Cryostat application will use the default port number `9091` to look for JMX connectable targets. | `false` | +| `core.discovery.kubernetes.portNumbers` | List of port numbers that the Cryostat application should look for in order to consider a target as JMX connectable | `[]` | ### Database Container diff --git a/charts/cryostat/templates/_helpers.tpl b/charts/cryostat/templates/_helpers.tpl index 2e096a77..e3f0b068 100644 --- a/charts/cryostat/templates/_helpers.tpl +++ b/charts/cryostat/templates/_helpers.tpl @@ -133,3 +133,16 @@ Generate or retrieve a default value for cookieSecret. {{- $newSecret | quote -}} {{- end }} {{- end }} + +{{/* + Get sanitized list or defaults (if not disabled) as comma-separated list +*/}} +{{- define "cryostat.commaSepList" -}} +{{- $l := index . 0 -}} +{{- $default := index . 1 -}} +{{- $disableDefaults := index . 2 -}} +{{- if and (not $l) (not $disableDefaults) -}} +{{- $l = list $default -}} +{{- end -}} +{{- join "," (default list $l | compact | uniq) | quote -}} +{{- end -}} diff --git a/charts/cryostat/templates/deployment.yaml b/charts/cryostat/templates/deployment.yaml index def3a3c7..12f6e8fc 100644 --- a/charts/cryostat/templates/deployment.yaml +++ b/charts/cryostat/templates/deployment.yaml @@ -91,6 +91,18 @@ spec: value: http://localhost:8800 - name: GRAFANA_DASHBOARD_URL value: http://localhost:3000 + {{- if .Values.core.discovery.kubernetes.enabled }} + - name: CRYOSTAT_DISCOVERY_KUBERNETES_ENABLED + value: "true" + {{- with .Values.core.discovery.kubernetes }} + - name: CRYOSTAT_DISCOVERY_KUBERNETES_NAMESPACES + value: {{ include "cryostat.commaSepList" (list .namespaces $.Release.Namespace .installNamespaceDisabled) }} + - name: CRYOSTAT_DISCOVERY_KUBERNETES_PORT_NAMES + value: {{ include "cryostat.commaSepList" (list .portNames "jfr-jmx" .builtInPortNamesDisabled) }} + - name: CRYOSTAT_DISCOVERY_KUBERNETES_PORT_NUMBERS + value: {{ include "cryostat.commaSepList" (list .portNumbers 9091 .builtInPortNumbersDisabled) }} + {{- end }} + {{- end }} ports: - containerPort: 8181 protocol: TCP diff --git a/charts/cryostat/templates/role.yaml b/charts/cryostat/templates/role.yaml index b47c0444..0945ae97 100644 --- a/charts/cryostat/templates/role.yaml +++ b/charts/cryostat/templates/role.yaml @@ -1,8 +1,12 @@ -{{- if .Values.rbac.create -}} +{{- define "createRole" -}} +{{- $ns := index . 0 -}} +{{- with index . 1 -}} +--- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: {{ include "cryostat.fullname" . }} + namespace: {{ $ns }} labels: {{- include "cryostat.labels" . | nindent 4 }} rules: @@ -36,4 +40,22 @@ rules: - deploymentconfigs verbs: - get -{{- end }} +- apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - get + - list +{{- end -}} +{{- end -}} + +{{- if and .Values.rbac.create .Values.core.discovery.kubernetes.enabled -}} +{{- $watchNs := compact (default list .Values.core.discovery.kubernetes.namespaces) | uniq -}} +{{- if and (not $watchNs) (not .Values.core.discovery.kubernetes.installNamespaceDisabled) -}} +{{- $watchNs = list .Release.Namespace -}} +{{- end -}} +{{- range $ns := $watchNs }} +{{ include "createRole" (list $ns $) }} +{{- end -}} +{{- end -}} diff --git a/charts/cryostat/templates/rolebinding.yaml b/charts/cryostat/templates/rolebinding.yaml index 22278c28..9354e7b6 100644 --- a/charts/cryostat/templates/rolebinding.yaml +++ b/charts/cryostat/templates/rolebinding.yaml @@ -1,8 +1,12 @@ -{{- if .Values.rbac.create -}} +{{- define "createRolebinding" -}} +{{- $ns := index . 0 -}} +{{- with index . 1 -}} +--- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: {{ include "cryostat.fullname" . }} + namespace: {{ $ns }} labels: {{- include "cryostat.labels" . | nindent 4 }} roleRef: @@ -13,4 +17,15 @@ subjects: - kind: ServiceAccount name: {{ include "cryostat.serviceAccountName" . }} namespace: {{ .Release.Namespace }} -{{- end }} +{{- end -}} +{{- end -}} + +{{- if and .Values.rbac.create .Values.core.discovery.kubernetes.enabled -}} +{{- $watchNs := compact (default list .Values.core.discovery.kubernetes.namespaces) | uniq -}} +{{- if and (not $watchNs) (not .Values.core.discovery.kubernetes.installNamespaceDisabled) -}} +{{- $watchNs = list .Release.Namespace -}} +{{- end -}} +{{- range $ns := $watchNs }} +{{ include "createRolebinding" (list $ns $) }} +{{- end -}} +{{- end -}} diff --git a/charts/cryostat/values.schema.json b/charts/cryostat/values.schema.json index e89096a5..8c5754b5 100644 --- a/charts/cryostat/values.schema.json +++ b/charts/cryostat/values.schema.json @@ -180,32 +180,60 @@ "type": "string", "description": "Name of the secret to extract password for credentials database.", "default": "" + }, + "discovery": { + "type": "object", + "properties": { + "kubernetes": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enables Kubernetes API discovery mechanism", + "default": true + }, + "installNamespaceDisabled": { + "type": "boolean", + "description": "When false and `namespaces` is empty, the Cryostat application will default to discovery targets in the install namespace (i.e. `{{ .Release.Namespace }}`)", + "default": false + }, + "namespaces": { + "type": "array", + "description": "List of namespaces whose workloads the Cryostat application should be permitted to access and profile", + "default": [], + "items": {} + }, + "builtInPortNamesDisabled": { + "type": "boolean", + "description": "When false and `portNames` is empty, the Cryostat application will use the default port name `jfr-jmx` to look for JMX connectable targets.", + "default": false + }, + "portNames": { + "type": "array", + "description": "List of port names that the Cryostat application should look for in order to consider a target as JMX connectable", + "default": [], + "items": {} + }, + "builtInPortNumbersDisabled": { + "type": "boolean", + "description": "When false and `portNumbers` is empty, the Cryostat application will use the default port number `9091` to look for JMX connectable targets.", + "default": false + }, + "portNumbers": { + "type": "array", + "description": "List of port numbers that the Cryostat application should look for in order to consider a target as JMX connectable", + "default": [], + "items": {} + } + } + } + } } } }, "db": { "type": "object", "properties": { - "image": { - "type": "object", - "properties": { - "repository": { - "type": "string", - "description": "Repository for the database container image", - "default": "quay.io/cryostat/cryostat-db" - }, - "pullPolicy": { - "type": "string", - "description": "Image pull policy for the database container image", - "default": "Always" - }, - "tag": { - "type": "string", - "description": "Tag for the database container image", - "default": "latest" - } - } - }, "securityContext": { "type": "object", "properties": { @@ -231,6 +259,26 @@ } } }, + "image": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "Repository for the database container image", + "default": "quay.io/cryostat/cryostat-db" + }, + "pullPolicy": { + "type": "string", + "description": "Image pull policy for the database container image", + "default": "Always" + }, + "tag": { + "type": "string", + "description": "Tag for the database container image", + "default": "latest" + } + } + }, "resources": { "type": "object", "description": "Resource requests/limits for the database container. See: [ResourceRequirements](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#resources)", diff --git a/charts/cryostat/values.yaml b/charts/cryostat/values.yaml index c05e1afa..d2a4e13c 100644 --- a/charts/cryostat/values.yaml +++ b/charts/cryostat/values.yaml @@ -60,6 +60,23 @@ core: - ALL ## @param core.databaseSecretName Name of the secret to extract password for credentials database. databaseSecretName: "" + ## @extra core.discovery Configuration options to the Cryostat application's target discovery mechanisms + discovery: + kubernetes: + ## @param core.discovery.kubernetes.enabled Enables Kubernetes API discovery mechanism + enabled: true + ## @param core.discovery.kubernetes.installNamespaceDisabled When false and `namespaces` is empty, the Cryostat application will default to discovery targets in the install namespace (i.e. `{{ .Release.Namespace }}`) + installNamespaceDisabled: false + ## @param core.discovery.kubernetes.namespaces [array] List of namespaces whose workloads the Cryostat application should be permitted to access and profile + namespaces: [] + ## @param core.discovery.kubernetes.builtInPortNamesDisabled When false and `portNames` is empty, the Cryostat application will use the default port name `jfr-jmx` to look for JMX connectable targets. + builtInPortNamesDisabled: false + ## @param core.discovery.kubernetes.portNames [array] List of port names that the Cryostat application should look for in order to consider a target as JMX connectable + portNames: [] + ## @param core.discovery.kubernetes.builtInPortNumbersDisabled When false and `portNumbers` is empty, the Cryostat application will use the default port number `9091` to look for JMX connectable targets. + builtInPortNumbersDisabled: false + ## @param core.discovery.kubernetes.portNumbers [array] List of port numbers that the Cryostat application should look for in order to consider a target as JMX connectable + portNumbers: [] ## @section Database Container ## @extra db Configuration for Cryostat's database