diff --git a/deployments/helm/.helmignore b/deployments/helm/.helmignore new file mode 100644 index 000000000..63cec6436 --- /dev/null +++ b/deployments/helm/.helmignore @@ -0,0 +1,24 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +.github diff --git a/deployments/helm/Chart.yaml b/deployments/helm/Chart.yaml new file mode 100644 index 000000000..b51be4b84 --- /dev/null +++ b/deployments/helm/Chart.yaml @@ -0,0 +1,12 @@ +apiVersion: v2 +name: beyla +version: 0.1.0 +appVersion: 1.2.0 +description: eBPF-based autoinstrumentation of HTTP and HTTPS services +sources: + - https://github.com/grafana/beyla +type: application +keywords: + - observability + - autoinstrumentation + - eBPF-based \ No newline at end of file diff --git a/deployments/helm/README.md b/deployments/helm/README.md new file mode 100644 index 000000000..94ac340ac --- /dev/null +++ b/deployments/helm/README.md @@ -0,0 +1,61 @@ +# beyla + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.2.0](https://img.shields.io/badge/AppVersion-1.2.0-informational?style=flat-square) + +eBPF-based autoinstrumentation of HTTP and HTTPS services + +## Source Code + +* + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | used for scheduling of pods based on affinity rules | +| config.create | bool | `true` | set to true, to use the below default configurations | +| config.data | object | `{"attributes":{"kubernetes":{"enable":true}},"discovery":{"services":[{"k8s_namespace":"."}]},"prometheus_export":{"path":"/metrics","port":9090}}` | default value of beyla configuration | +| config.name | string | `""` | | +| env | object | `{"BEYLA_PRINT_TRACES":"true"}` | extra environment variables | +| envValueFrom | object | `{}` | extra environment variables to be set from resources such as k8s configMaps/secrets | +| fullnameOverride | string | `""` | Overrides the chart's computed fullname. | +| global.image.pullSecrets | list | `[]` | Optional set of global image pull secrets. | +| global.image.registry | string | `""` | Global image registry to use if it needs to be overridden for some specific use cases (e.g local registries, custom images, ...) | +| image.digest | string | `nil` | Beyla image's SHA256 digest (either in format "sha256:XYZ" or "XYZ"). When set, will override `image.tag`. | +| image.pullPolicy | string | `"IfNotPresent"` | Beyla image pull policy. | +| image.pullSecrets | list | `[]` | Optional set of image pull secrets. | +| image.registry | string | `"docker.io"` | Beyla image registry (defaults to docker.io) | +| image.repository | string | `"grafana/beyla"` | Beyla image repository. | +| image.tag | string | `nil` | Beyla image tag. When empty, the Chart's appVersion is used. | +| nameOverride | string | `""` | Overrides the chart's name | +| namespaceOverride | string | `""` | Override the deployment namespace | +| nodeSelector | object | `{}` | The nodeSelector field allows user to constrain which nodes your DaemonSet pods are scheduled to based on labels on the node | +| podSecurityContext | object | `{}` | | +| rbac.create | bool | `true` | Whether to create RBAC resources for Belya | +| rbac.extraClusterRoleRules | list | `[]` | Extra custer roles to be created for Belya | +| resources | object | `{}` | | +| securityContext | object | `{}` | | +| service.annotations | object | `{}` | Service annotations. | +| service.appProtocol | string | `""` | Adds the appProtocol field to the service. This allows to work with istio protocol selection. Ex: "http" or "tcp" | +| service.clusterIP | string | `""` | cluster IP | +| service.enabled | bool | `true` | whether to create a service for internal metrics | +| service.labels | object | `{}` | Service labels. | +| service.loadBalancerClass | string | `""` | loadbalancer class name | +| service.loadBalancerIP | string | `""` | loadbalancer IP | +| service.loadBalancerSourceRanges | list | `[]` | source ranges for loadbalancer | +| service.port | int | `80` | service port | +| service.portName | string | `"service"` | name of the port for internal metrics service. | +| service.targetPort | int | `9090` | targetPort has to be configured based on the values of `BEYLA_INTERNAL_METRICS_PROMETHEUS_PORT` environment variable or the value of `prometheus_export.port` from beyla configuration file. see more at https://grafana.com/docs/beyla/latest/configure/options/#internal-metrics-reporter | +| service.type | string | `"ClusterIP"` | type of the service | +| serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| serviceAccount.automount | bool | `true` | Automatically mount a ServiceAccount's API credentials? | +| serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| serviceAccount.labels | object | `{}` | ServiceAccount labels. | +| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| tolerations | list | `[]` | Tolerations allow pods to be scheduled on nodes with specific taints | +| updateStrategy.type | string | `"RollingUpdate"` | update strategy type | +| volumeMounts | list | `[]` | Additional volumeMounts on the output Deployment definition. | +| volumes | list | `[]` | Additional volumes on the output daemonset definition. | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.13.1](https://github.com/norwoodj/helm-docs/releases/v1.13.1) diff --git a/deployments/helm/templates/_helpers.tpl b/deployments/helm/templates/_helpers.tpl new file mode 100644 index 000000000..6d34b8fb0 --- /dev/null +++ b/deployments/helm/templates/_helpers.tpl @@ -0,0 +1,92 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "beyla.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "beyla.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "beyla.namespace" -}} +{{- if .Values.namespaceOverride }} +{{- .Values.namespaceOverride }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} + + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "beyla.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "beyla.labels" -}} +helm.sh/chart: {{ include "beyla.chart" . }} +{{ include "beyla.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "beyla.selectorLabels" -}} +app.kubernetes.io/name: {{ include "beyla.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "beyla.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "beyla.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + + +{{/* +Calculate name of image ID to use for "beyla". +*/}} +{{- define "beyla.imageId" -}} +{{- if .Values.image.digest }} +{{- $digest := .Values.image.digest }} +{{- if not (hasPrefix "sha256:" $digest) }} +{{- $digest = printf "sha256:%s" $digest }} +{{- end }} +{{- printf "@%s" $digest }} +{{- else if .Values.image.tag }} +{{- printf ":%s" .Values.image.tag }} +{{- else }} +{{- printf ":%s" .Chart.AppVersion }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/deployments/helm/templates/cluster-role-binding.yaml b/deployments/helm/templates/cluster-role-binding.yaml new file mode 100644 index 000000000..41ada6d01 --- /dev/null +++ b/deployments/helm/templates/cluster-role-binding.yaml @@ -0,0 +1,20 @@ +{{- if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "beyla.fullname" . }} + labels: + {{- include "beyla.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +subjects: + - kind: ServiceAccount + name: {{ include "beyla.serviceAccountName" . }} + namespace: {{ include "beyla.namespace" .}} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "beyla.fullname" . }} +{{- end }} diff --git a/deployments/helm/templates/cluster-role.yaml b/deployments/helm/templates/cluster-role.yaml new file mode 100644 index 000000000..e415ea544 --- /dev/null +++ b/deployments/helm/templates/cluster-role.yaml @@ -0,0 +1,22 @@ +{{- if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "beyla.fullname" . }} + labels: + {{- include "beyla.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: ["apps"] + resources: ["replicasets"] + verbs: ["list", "watch"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["list", "watch"] + {{- with .Values.rbac.extraClusterRoleRules }} + {{- toYaml . | nindent 2 }} + {{- end}} +{{- end }} diff --git a/deployments/helm/templates/configmap.yaml b/deployments/helm/templates/configmap.yaml new file mode 100644 index 000000000..cd08c0901 --- /dev/null +++ b/deployments/helm/templates/configmap.yaml @@ -0,0 +1,19 @@ +{{- if and (not .Values.config.create) (eq .Values.config.name "") }} + {{- fail "if .Values.config.name is not set, then .Values.config.create should be set to true to use default configuration" }} +{{- end }} +{{- if and (.Values.config.create) (eq .Values.config.name "") }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "beyla.fullname" . }} + namespace: {{ include "beyla.namespace" . }} + labels: + {{- include "beyla.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +data: + beyla-config.yml: | + {{- toYaml .Values.config.data | nindent 4}} +{{- end }} diff --git a/deployments/helm/templates/daemon-set.yml b/deployments/helm/templates/daemon-set.yml new file mode 100644 index 000000000..30f89d452 --- /dev/null +++ b/deployments/helm/templates/daemon-set.yml @@ -0,0 +1,76 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "beyla.fullname" . }} + namespace: {{ include "beyla.namespace" .}} + labels: + {{- include "beyla.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: +{{ include "beyla.selectorLabels" . | indent 6 }} + {{- with .Values.updateStrategy }} + updateStrategy: + {{- toYaml . | trim | nindent 4 }} + {{- end }} + template: + metadata: + labels: +{{ include "beyla.selectorLabels" . | indent 8 }} + spec: + {{- if .Values.serviceAccount.create }} + serviceAccountName: {{ include "beyla.serviceAccountName" . }} + {{- end }} + hostPID: true #important! + containers: + - name: beyla + image: {{ .Values.global.image.registry | default .Values.image.registry }}/{{ .Values.image.repository }}{{ include "beyla.imageId" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + privileged: true + ports: + - containerPort: {{ .Values.service.targetPort }} + protocol: TCP + env: + - name: BEYLA_CONFIG_PATH + value: "/etc/beyla/config/beyla-config.yml" + {{- range $key, $value := .Values.env }} + - name: {{ $key }} + value: "{{ $value }}" + {{- end }} + {{- range $key, $value := .Values.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 16 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- tpl (toYaml .) $ | nindent 12 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - mountPath: /etc/beyla/config + name: beyla-config + {{- if or .Values.global.image.pullSecrets .Values.image.pullSecrets }} + imagePullSecrets: + {{- if .Values.global.image.pullSecrets }} + {{- toYaml .Values.global.image.pullSecrets | nindent 4 }} + {{- else }} + {{- toYaml .Values.image.pullSecrets | nindent 4 }} + {{- end }} + {{- end }} + volumes: + - name: beyla-config + configMap: + name: {{ default (include "beyla.fullname" .) .Values.config.name }} \ No newline at end of file diff --git a/deployments/helm/templates/service.yaml b/deployments/helm/templates/service.yaml new file mode 100644 index 000000000..a3e252068 --- /dev/null +++ b/deployments/helm/templates/service.yaml @@ -0,0 +1,58 @@ +{{- if .Values.service.enabled }} +{{- $root := . }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "beyla.fullname" . }} + namespace: {{ include "beyla.namespace" .}} + labels: + {{- include "beyla.labels" . | nindent 4 }} + {{- with .Values.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.service.annotations }} + annotations: + {{- tpl (toYaml . | nindent 4) $root }} + {{- end }} +spec: + {{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }} + type: ClusterIP + {{- with .Values.service.clusterIP }} + clusterIP: {{ . }} + {{- end }} + {{- else if eq .Values.service.type "LoadBalancer" }} + type: LoadBalancer + {{- with .Values.service.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- with .Values.service.loadBalancerClass }} + loadBalancerClass: {{ . }} + {{- end }} + {{- with .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- else }} + type: {{ .Values.service.type }} + {{- end }} + {{- with .Values.service.externalIPs }} + externalIPs: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ . }} + {{- end }} + ports: + - name: {{ .Values.service.portName }} + port: {{ .Values.service.port }} + protocol: TCP + targetPort: {{ .Values.service.targetPort }} + {{- with .Values.service.appProtocol }} + appProtocol: {{ . }} + {{- end }} + {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + selector: + {{- include "beyla.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/deployments/helm/templates/serviceaccount.yaml b/deployments/helm/templates/serviceaccount.yaml new file mode 100644 index 000000000..54c876a29 --- /dev/null +++ b/deployments/helm/templates/serviceaccount.yaml @@ -0,0 +1,17 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "beyla.serviceAccountName" . }} + namespace: {{ include "beyla.namespace" .}} + labels: + {{- include "beyla.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/deployments/helm/values.yaml b/deployments/helm/values.yaml new file mode 100644 index 000000000..8c8023371 --- /dev/null +++ b/deployments/helm/values.yaml @@ -0,0 +1,198 @@ +## Global properties for image pulling override the values defined under `image.registry`. +## If you want to override only one image registry, use the specific fields but if you want to override them all, use `global.image.registry` +global: + image: + # -- Global image registry to use if it needs to be overridden for some specific use cases (e.g local registries, custom images, ...) + registry: "" + + # -- Optional set of global image pull secrets. + pullSecrets: [] + +image: + # -- Beyla image registry (defaults to docker.io) + registry: "docker.io" + # -- Beyla image repository. + repository: grafana/beyla + # -- (string) Beyla image tag. When empty, the Chart's appVersion is + # used. + tag: null + # -- Beyla image's SHA256 digest (either in format "sha256:XYZ" or "XYZ"). When set, will override `image.tag`. + digest: null + # -- Beyla image pull policy. + pullPolicy: IfNotPresent + # -- Optional set of image pull secrets. + pullSecrets: [] + +# -- Overrides the chart's name +nameOverride: "" + +# -- Overrides the chart's computed fullname. +fullnameOverride: "" + +# -- Override the deployment namespace +namespaceOverride: "" + +## DaemonSet annotations +# annotations: {} + +rbac: + # -- Whether to create RBAC resources for Belya + create: true + # -- Extra custer roles to be created for Belya + extraClusterRoleRules: [] + # - apiGroups: [] + # resources: [] + +serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Automatically mount a ServiceAccount's API credentials? + automount: true + # -- ServiceAccount labels. + labels: {} + # -- Annotations to add to the service account + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +## -- Expose the beyla internal metrics service to be accessed from outside the cluster (LoadBalancer service). +## or access it from within the cluster (ClusterIP service). Set the service type and the port to serve it. +## ref: http://kubernetes.io/docs/user-guide/services/ +## +service: + # -- whether to create a service for internal metrics + enabled: false + # -- type of the service + type: ClusterIP + # -- cluster IP + clusterIP: "" + # -- loadbalancer IP + loadBalancerIP: "" + # -- loadbalancer class name + loadBalancerClass: "" + # -- source ranges for loadbalancer + loadBalancerSourceRanges: [] + # -- service port + port: 80 + # -- targetPort has to be configured based on the values of `BEYLA_INTERNAL_METRICS_PROMETHEUS_PORT` environment variable + # or the value of `prometheus_export.port` from beyla configuration file. + # see more at https://grafana.com/docs/beyla/latest/configure/options/#internal-metrics-reporter + targetPort: 9090 + # -- Service annotations. + annotations: {} + # -- Service labels. + labels: {} + # -- name of the port for internal metrics service. + portName: service + # -- Adds the appProtocol field to the service. This allows to work with istio protocol selection. Ex: "http" or "tcp" + appProtocol: "" + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + + +## -- See `kubectl explain daemonset.spec.updateStrategy` for more +## ref: https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/#daemonset-update-strategy +updateStrategy: + # -- update strategy type + type: RollingUpdate + + +# -- Additional volumes on the output daemonset definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# -- Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +# -- The nodeSelector field allows user to constrain which nodes your DaemonSet pods are scheduled to based on labels on the node +nodeSelector: {} + +# -- Tolerations allow pods to be scheduled on nodes with specific taints +tolerations: [] + +# -- used for scheduling of pods based on affinity rules +affinity: {} + +## More configuration options available at https://grafana.com/docs/beyla/latest/configure/options/ +## The below default configuration +## 1. looks for ALL the services in the host +## 2. export metrics as prometheus metrics by default at 9090 port +## 3. enables kubernetes attribute +## Note: The default configuration is used if config.create=true and config.name="" +config: + # -- set to true, to use the below default configurations + create: true + ## -- Provide the name of the external configmap containing the beyla configuration. + ## To create configmap from configuration file, user can use the below command. Note: The name 'beyla-config.yaml' is important. + ## `kubectl create cm --from-file=beyla-config.yaml= -n ` + ## If empty, default configuration below is used. + name: "" + # -- default value of beyla configuration + data: + # open_port: 8443 + # routes: + # unmatched: heuristic + # log_level: info + # otel_traces_export: + # endpoint: http://grafana-agent:4318 + ## or alternatively use + # grafana: + # otlp: + # cloud_zone: prod-eu-west-0 + # cloud_instance_id: 123456 + # cloud_api_key: + discovery: + services: + - k8s_namespace: . + attributes: + kubernetes: + enable: true + ## internal metrics reporting. Refer: https://grafana.com/docs/beyla/latest/configure/options/#internal-metrics-reporter + ## If set, user can expose the metrics endpoint via k8s service by configuring .Values.service section + prometheus_export: + port: 9090 + path: /metrics + +## Env variables that will override configmap values +## For example: +## BEYLA_INTERNAL_METRICS_PROMETHEUS_PORT: 9090 +# -- extra environment variables +env: + #BEYLA_INTERNAL_METRICS_PROMETHEUS_PORT: 9090 + BEYLA_PRINT_TRACES: "true" + +# -- extra environment variables to be set from resources such as k8s configMaps/secrets +envValueFrom: {} + # ENV_NAME: + # secretKeyRef: + # name: secret-name + # key: value_key