diff --git a/charts/falco/CHANGELOG.md b/charts/falco/CHANGELOG.md index 4e308328..060675b1 100644 --- a/charts/falco/CHANGELOG.md +++ b/charts/falco/CHANGELOG.md @@ -3,6 +3,10 @@ This file documents all notable changes to Falco Helm Chart. The release numbering uses [semantic versioning](http://semver.org). +## v4.9.1 + +* feat(falco): add labels and annotations to the metrics service + ## v4.9.0 * Bump Falco to v0.39.0 * update(falco): add new configuration entries for Falco diff --git a/charts/falco/Chart.yaml b/charts/falco/Chart.yaml index 148c87f6..aaf3a29f 100644 --- a/charts/falco/Chart.yaml +++ b/charts/falco/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: falco -version: 4.9.0 +version: 4.9.1 appVersion: "0.39.0" description: Falco keywords: diff --git a/charts/falco/README.md b/charts/falco/README.md index b8c0490f..d0da8023 100644 --- a/charts/falco/README.md +++ b/charts/falco/README.md @@ -581,7 +581,7 @@ If you use a Proxy in your cluster, the requests between `Falco` and `Falcosidek ## Configuration -The following table lists the main configurable parameters of the falco chart v4.9.0 and their default values. See [values.yaml](./values.yaml) for full list. +The following table lists the main configurable parameters of the falco chart v4.9.1 and their default values. See [values.yaml](./values.yaml) for full list. ## Values @@ -741,7 +741,7 @@ The following table lists the main configurable parameters of the falco chart v4 | image.repository | string | `"falcosecurity/falco-no-driver"` | The image repository to pull from | | image.tag | string | `""` | The image tag to pull. Overrides the image tag whose default is the chart appVersion. | | imagePullSecrets | list | `[]` | Secrets containing credentials when pulling from private/secure registries. | -| metrics | object | `{"convertMemoryToMB":true,"enabled":false,"includeEmptyValues":false,"interval":"1h","kernelEventCountersEnabled":true,"kernelEventCountersPerCPUEnabled":false,"libbpfStatsEnabled":true,"outputRule":false,"resourceUtilizationEnabled":true,"rulesCountersEnabled":true,"service":{"create":true,"ports":{"metrics":{"port":8765,"protocol":"TCP","targetPort":8765}},"type":"ClusterIP"},"stateCountersEnabled":true}` | metrics configures Falco to enable and expose the metrics. | +| metrics | object | `{"convertMemoryToMB":true,"enabled":false,"includeEmptyValues":false,"interval":"1h","kernelEventCountersEnabled":true,"kernelEventCountersPerCPUEnabled":false,"libbpfStatsEnabled":true,"outputRule":false,"resourceUtilizationEnabled":true,"rulesCountersEnabled":true,"service":{"annotations":{},"create":true,"labels":{},"ports":{"metrics":{"port":8765,"protocol":"TCP","targetPort":8765}},"type":"ClusterIP"},"stateCountersEnabled":true}` | metrics configures Falco to enable and expose the metrics. | | metrics.convertMemoryToMB | bool | `true` | convertMemoryToMB specifies whether the memory should be converted to mb. | | metrics.enabled | bool | `false` | enabled specifies whether the metrics should be enabled. | | metrics.includeEmptyValues | bool | `false` | includeEmptyValues specifies whether the empty values should be included in the metrics. | @@ -751,8 +751,10 @@ The following table lists the main configurable parameters of the falco chart v4 | metrics.outputRule | bool | `false` | outputRule enables seamless metrics and performance monitoring, we recommend emitting metrics as the rule "Falco internal: metrics snapshot". This option is particularly useful when Falco logs are preserved in a data lake. Please note that to use this option, the Falco rules config `priority` must be set to `info` at a minimum. | | metrics.resourceUtilizationEnabled | bool | `true` | resourceUtilizationEnabled`: Emit CPU and memory usage metrics. CPU usage is reported as a percentage of one CPU and can be normalized to the total number of CPUs to determine overall usage. Memory metrics are provided in raw units (`kb` for `RSS`, `PSS` and `VSZ` or `bytes` for `container_memory_used`) and can be uniformly converted to megabytes (MB) using the `convert_memory_to_mb` functionality. In environments such as Kubernetes when deployed as daemonset, it is crucial to track Falco's container memory usage. To customize the path of the memory metric file, you can create an environment variable named `FALCO_CGROUP_MEM_PATH` and set it to the desired file path. By default, Falco uses the file `/sys/fs/cgroup/memory/memory.usage_in_bytes` to monitor container memory usage, which aligns with Kubernetes' `container_memory_working_set_bytes` metric. Finally, we emit the overall host CPU and memory usages, along with the total number of processes and open file descriptors (fds) on the host, obtained from the proc file system unrelated to Falco's monitoring. These metrics help assess Falco's usage in relation to the server's workload intensity. | | metrics.rulesCountersEnabled | bool | `true` | rulesCountersEnabled specifies whether the counts for each rule should be emitted. | -| metrics.service | object | `{"create":true,"ports":{"metrics":{"port":8765,"protocol":"TCP","targetPort":8765}},"type":"ClusterIP"}` | service exposes the metrics service to be accessed from within the cluster. ref: https://kubernetes.io/docs/concepts/services-networking/service/ | +| metrics.service | object | `{"annotations":{},"create":true,"labels":{},"ports":{"metrics":{"port":8765,"protocol":"TCP","targetPort":8765}},"type":"ClusterIP"}` | service exposes the metrics service to be accessed from within the cluster. ref: https://kubernetes.io/docs/concepts/services-networking/service/ | +| metrics.service.annotations | object | `{}` | annotations to add to the service. | | metrics.service.create | bool | `true` | create specifies whether a service should be created. | +| metrics.service.labels | object | `{}` | labels to add to the service. | | metrics.service.ports | object | `{"metrics":{"port":8765,"protocol":"TCP","targetPort":8765}}` | ports denotes all the ports on which the Service will listen. | | metrics.service.ports.metrics | object | `{"port":8765,"protocol":"TCP","targetPort":8765}` | metrics denotes a listening service named "metrics". | | metrics.service.ports.metrics.port | int | `8765` | port is the port on which the Service will listen. | diff --git a/charts/falco/templates/service.yaml b/charts/falco/templates/service.yaml index d2093ec2..4121a503 100644 --- a/charts/falco/templates/service.yaml +++ b/charts/falco/templates/service.yaml @@ -6,7 +6,14 @@ metadata: namespace: {{ include "falco.namespace" . }} labels: {{- include "falco.labels" . | nindent 4 }} + {{- with .Values.metrics.service.labels }} + {{ toYaml . | nindent 4 }} + {{- end }} type: "falco-metrics" + {{- with .Values.metrics.service.annotations }} + annotations: + {{ toYaml . | nindent 4 }} + {{- end }} spec: type: {{ .Values.metrics.service.type }} ports: diff --git a/charts/falco/tests/unit/chartInfo.go b/charts/falco/tests/unit/chartInfo.go new file mode 100644 index 00000000..11b4b3d9 --- /dev/null +++ b/charts/falco/tests/unit/chartInfo.go @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 The Falco Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package unit + +import ( + "testing" + + "github.com/gruntwork-io/terratest/modules/helm" + "gopkg.in/yaml.v3" +) + +func chartInfo(t *testing.T, chartPath string) (map[string]interface{}, error) { + // Get chart info. + output, err := helm.RunHelmCommandAndGetOutputE(t, &helm.Options{}, "show", "chart", chartPath) + if err != nil { + return nil, err + } + chartInfo := map[string]interface{}{} + err = yaml.Unmarshal([]byte(output), &chartInfo) + return chartInfo, err +} diff --git a/charts/falco/tests/unit/serviceTemplate_test.go b/charts/falco/tests/unit/serviceTemplate_test.go new file mode 100644 index 00000000..861159a6 --- /dev/null +++ b/charts/falco/tests/unit/serviceTemplate_test.go @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 The Falco Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package unit + +import ( + "fmt" + "path/filepath" + "testing" + + "github.com/gruntwork-io/terratest/modules/helm" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + corev1 "k8s.io/api/core/v1" +) + +type serviceTemplateTest struct { + suite.Suite + chartPath string + releaseName string + namespace string + templates []string +} + +func TestServiceTemplate(t *testing.T) { + t.Parallel() + + chartFullPath, err := filepath.Abs(chartPath) + require.NoError(t, err) + + suite.Run(t, &serviceTemplateTest{ + Suite: suite.Suite{}, + chartPath: chartFullPath, + releaseName: "falco-test", + namespace: "falco-namespace-test", + templates: []string{"templates/service.yaml"}, + }) +} + +func (s *serviceTemplateTest) TestCreationDefaultValues() { + // Render the service and check that it has not been rendered. + _, err := helm.RenderTemplateE(s.T(), &helm.Options{}, s.chartPath, s.releaseName, s.templates) + s.Error(err, "should error") + s.Equal("error while running command: exit status 1; Error: could not find template templates/service.yaml in chart", err.Error()) +} + +func (s *serviceTemplateTest) TestDefaultLabelsValues() { + options := &helm.Options{SetValues: map[string]string{"metrics.enabled": "true"}} + output, err := helm.RenderTemplateE(s.T(), options, s.chartPath, s.releaseName, s.templates) + s.NoError(err, "should render template") + + cInfo, err := chartInfo(s.T(), s.chartPath) + s.NoError(err) + // Get app version. + appVersion, found := cInfo["appVersion"] + s.True(found, "should find app version in chart info") + appVersion = appVersion.(string) + // Get chart version. + chartVersion, found := cInfo["version"] + s.True(found, "should find chart version in chart info") + // Get chart name. + chartName, found := cInfo["name"] + s.True(found, "should find chart name in chart info") + chartName = chartName.(string) + expectedLabels := map[string]string{ + "helm.sh/chart": fmt.Sprintf("%s-%s", chartName, chartVersion), + "app.kubernetes.io/name": chartName.(string), + "app.kubernetes.io/instance": s.releaseName, + "app.kubernetes.io/version": appVersion.(string), + "app.kubernetes.io/managed-by": "Helm", + "type": "falco-metrics", + } + var svc corev1.Service + helm.UnmarshalK8SYaml(s.T(), output, &svc) + labels := svc.GetLabels() + for key, value := range labels { + expectedVal := expectedLabels[key] + s.Equal(expectedVal, value) + } + + for key, value := range expectedLabels { + expectedVal := labels[key] + s.Equal(expectedVal, value) + } +} + + +func (s *serviceTemplateTest) TestCustomLabelsValues() { + options := &helm.Options{SetValues: map[string]string{"metrics.enabled": "true", + "metrics.service.labels.customLabel": "customLabelValues"}} + output, err := helm.RenderTemplateE(s.T(), options, s.chartPath, s.releaseName, s.templates) + + + s.NoError(err, "should render template") + + cInfo, err := chartInfo(s.T(), s.chartPath) + s.NoError(err) + // Get app version. + appVersion, found := cInfo["appVersion"] + s.True(found, "should find app version in chart info") + appVersion = appVersion.(string) + // Get chart version. + chartVersion, found := cInfo["version"] + s.True(found, "should find chart version in chart info") + // Get chart name. + chartName, found := cInfo["name"] + s.True(found, "should find chart name in chart info") + chartName = chartName.(string) + expectedLabels := map[string]string{ + "helm.sh/chart": fmt.Sprintf("%s-%s", chartName, chartVersion), + "app.kubernetes.io/name": chartName.(string), + "app.kubernetes.io/instance": s.releaseName, + "app.kubernetes.io/version": appVersion.(string), + "app.kubernetes.io/managed-by": "Helm", + "type": "falco-metrics", + "customLabel": "customLabelValues", + } + var svc corev1.Service + helm.UnmarshalK8SYaml(s.T(), output, &svc) + labels := svc.GetLabels() + for key, value := range labels { + expectedVal := expectedLabels[key] + s.Equal(expectedVal, value) + } + + for key, value := range expectedLabels { + expectedVal := labels[key] + s.Equal(expectedVal, value) + } + +} + +func (s *serviceTemplateTest) TestDefaultAnnotationsValues() { + options := &helm.Options{SetValues: map[string]string{"metrics.enabled": "true"}} + output, err := helm.RenderTemplateE(s.T(), options, s.chartPath, s.releaseName, s.templates) + + s.NoError(err) + + var svc corev1.Service + helm.UnmarshalK8SYaml(s.T(), output, &svc) + s.Nil(svc.Annotations, "should be nil") +} + +func (s *serviceTemplateTest) TestCustomAnnotationsValues() { + values := map[string]string{ + "metrics.enabled": "true", + "metrics.service.annotations.annotation1": "customAnnotation1", + "metrics.service.annotations.annotation2": "customAnnotation2", + } + annotations := map[string]string{ + "annotation1": "customAnnotation1", + "annotation2": "customAnnotation2", + } + options := &helm.Options{SetValues: values} + output, err := helm.RenderTemplateE(s.T(), options, s.chartPath, s.releaseName, s.templates) + s.NoError(err) + + var svc corev1.Service + helm.UnmarshalK8SYaml(s.T(), output, &svc) + s.Len(svc.Annotations, 2) + + for key, value := range svc.Annotations { + expectedVal := annotations[key] + s.Equal(expectedVal, value) + } +} \ No newline at end of file diff --git a/charts/falco/values.yaml b/charts/falco/values.yaml index 761e76b7..aaf0b14c 100644 --- a/charts/falco/values.yaml +++ b/charts/falco/values.yaml @@ -250,6 +250,10 @@ metrics: # -- type denotes the service type. Setting it to "ClusterIP" we ensure that are accessible # from within the cluster. type: ClusterIP + # -- labels to add to the service. + labels: {} + # -- annotations to add to the service. + annotations: {} # -- ports denotes all the ports on which the Service will listen. ports: # -- metrics denotes a listening service named "metrics".