From e9f61e1e163a583a668c52dd85b43526b4622c31 Mon Sep 17 00:00:00 2001 From: Michael Montgomery Date: Mon, 24 Nov 2025 15:26:01 -0600 Subject: [PATCH 1/4] Remove docs and unit tests surrounding running agent as non-root Signed-off-by: Michael Montgomery --- config/recipes/elastic-agent/README.asciidoc | 4 -- .../fleet-kubernetes-integration.yaml | 12 ++-- test/e2e/agent/recipes_test.go | 63 ---------------- test/e2e/test/helper/yaml.go | 72 +------------------ 4 files changed, 9 insertions(+), 142 deletions(-) diff --git a/config/recipes/elastic-agent/README.asciidoc b/config/recipes/elastic-agent/README.asciidoc index c5ceb57e1f..8a45b3f980 100644 --- a/config/recipes/elastic-agent/README.asciidoc +++ b/config/recipes/elastic-agent/README.asciidoc @@ -31,10 +31,6 @@ Deploys two Elasticsearch clusters and two Kibana instances together with single Deploys Elastic Agent as a DaemonSet in Fleet mode with System and Kubernetes integrations enabled. System integration collects syslog logs, auth logs and system metrics (for CPU, I/O, filesystem, memory, network, process and others). Kubernetes integrations collects API server, Container, Event, Node, Pod, Volume and system metrics. -===== System and Kubernetes integrations running as non-root - `fleet-kubernetes-integration-nonroot.yaml` - -The provided example is functionally identical to the previous section but runs the Elastic Agent processes (both the Elastic Agent running as the Fleet server and the Elastic Agent connected to Fleet) as a non-root user by utilizing a DaemonSet to ensure directory and file permissions. *Note* The DaemonSet itself must run as root to set up permissions and ECK >= 2.10.0 is required. - ===== Custom logs integration with autodiscover - `fleet-custom-logs-integration.yaml` Deploys Elastic Agent as a DaemonSet in Fleet mode with Custom Logs integration enabled. Collects logs from all Pods in the `default` namespace using autodiscover feature. diff --git a/config/recipes/elastic-agent/fleet-kubernetes-integration.yaml b/config/recipes/elastic-agent/fleet-kubernetes-integration.yaml index 5380f839db..6ba84f572e 100644 --- a/config/recipes/elastic-agent/fleet-kubernetes-integration.yaml +++ b/config/recipes/elastic-agent/fleet-kubernetes-integration.yaml @@ -80,8 +80,10 @@ spec: spec: serviceAccountName: fleet-server automountServiceAccountToken: true - securityContext: - runAsUser: 0 + # Since Elastic Agent v8.16.0, the runAsUser: 0 is not needed + # as Agent chowns the data directory to the container user id. + # securityContext: + # runAsUser: 0 --- apiVersion: agent.k8s.elastic.co/v1alpha1 kind: Agent @@ -114,8 +116,10 @@ spec: hostNetwork: true dnsPolicy: ClusterFirstWithHostNet automountServiceAccountToken: true - securityContext: - runAsUser: 0 + # Since Elastic Agent v8.16.0, the runAsUser: 0 is not needed + # as Agent chowns the data directory to the container user id. + # securityContext: + # runAsUser: 0 --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole diff --git a/test/e2e/agent/recipes_test.go b/test/e2e/agent/recipes_test.go index ba726b1409..8d2954d174 100644 --- a/test/e2e/agent/recipes_test.go +++ b/test/e2e/agent/recipes_test.go @@ -124,69 +124,6 @@ func TestFleetKubernetesIntegrationRecipe(t *testing.T) { runAgentRecipe(t, "fleet-kubernetes-integration.yaml", customize) } -func TestFleetKubernetesNonRootIntegrationRecipe(t *testing.T) { - v := version.MustParse(test.Ctx().ElasticStackVersion) - - if (v.GE(version.MinFor(7, 17, 28)) && v.LT(version.MinFor(8, 0, 0))) || - (v.GE(version.MinFor(8, 1, 3)) && v.LT(version.MinFor(8, 2, 0))) { - t.Skipf("Skipped as version %s is affected by https://github.com/elastic/kibana/pull/236788", v) - } - - // https://github.com/elastic/cloud-on-k8s/issues/6331 - if v.LT(version.MinFor(8, 7, 0)) && v.GE(version.MinFor(8, 6, 0)) { - t.SkipNow() - } - - if (v.GE(version.MinFor(9, 0, 1)) && v.LE(version.MinFor(9, 0, 4))) || - (v.EQ(version.From(9, 1, 0))) || - (v.EQ(version.MustParse("9.3.0-SNAPSHOT"))) { // TODO remove once https://github.com/elastic/kibana/pull/230211 is backported to 9.3.x - t.Skipf("Skipped as version %s is affected by https://github.com/elastic/kibana/pull/230211", v) - } - - // Do not test between 9.1.0 and 9.1.5 due to broken ssl settings in Kibana, see https://github.com/elastic/cloud-on-k8s/issues/8820 - if v.GE(version.From(9, 1, 0)) && v.LT(version.From(9, 1, 5)) { - t.Skipf("Skipped as version %s is affected by https://github.com/elastic/kibana/issues/233780", v) - } - - // The recipe does not work fully within an openshift cluster without modifications. - if test.Ctx().OcpCluster { - t.SkipNow() - } - - customize := func(builder agent.Builder) agent.Builder { - if !builder.Agent.Spec.FleetServerEnabled { - return builder - } - - return builder. - WithFleetAgentDataStreamsValidation(). - // TODO API server should generate event in time but on kind we see repeatedly no metrics being reported in time - // see https://github.com/elastic/cloud-on-k8s/issues/4092 - // WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "kubernetes.apiserver", "k8s")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "kubernetes.container", "default")). - // Might not generate an event in time for this check to succeed in all environments - // WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "kubernetes.event", "k8s")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "kubernetes.node", "default")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "kubernetes.pod", "default")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "kubernetes.proxy", "default")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "kubernetes.system", "default")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "kubernetes.volume", "default")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "system.cpu", "default")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "system.diskio", "default")). - // to be reinstated once https://github.com/elastic/beats/issues/30590 is addressed - // WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "system.fsstat", "default")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "system.load", "default")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "system.memory", "default")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "system.network", "default")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "system.process", "default")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "system.process.summary", "default")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "system.socket_summary", "default")). - WithDefaultESValidation(agent.HasWorkingDataStream(agent.MetricsType, "system.uptime", "default")) - } - - runAgentRecipe(t, "fleet-kubernetes-integration-nonroot.yaml", customize) -} - func TestFleetCustomLogsIntegrationRecipe(t *testing.T) { v := version.MustParse(test.Ctx().ElasticStackVersion) diff --git a/test/e2e/test/helper/yaml.go b/test/e2e/test/helper/yaml.go index 984e4f03f7..0c4f46cdca 100644 --- a/test/e2e/test/helper/yaml.go +++ b/test/e2e/test/helper/yaml.go @@ -359,12 +359,8 @@ func transformToE2E(namespace, fullTestName, suffix string, transformers []Build decodedObj.Namespace = namespace decodedObj.Name = decodedObj.Name + "-" + suffix case *appsv1.DaemonSet: - name := decodedObj.Name + "-" + suffix decodedObj.Namespace = namespace - decodedObj.Name = name - decodedObj.Spec.Selector.MatchLabels["app.kubernetes.io/instance"] = name - decodedObj.Spec.Template.ObjectMeta.Labels["app.kubernetes.io/instance"] = name - maybeMutateForAgentNonRootTests(decodedObj, namespace, suffix) + decodedObj.Name = decodedObj.Name + "-" + suffix } if builder != nil { @@ -389,30 +385,6 @@ func transformToE2E(namespace, fullTestName, suffix string, transformers []Build return builders, otherObjects } -// maybeMutateForAgentNonRootTests will possibly mutate the given daemonset when -// running tests for Elastic Agent running as non-root. This is required as the -// directories depend on both the namespace and the random suffix of the e2e tests. -func maybeMutateForAgentNonRootTests(ds *appsv1.DaemonSet, namespace, suffix string) { - for i, init := range ds.Spec.Template.Spec.InitContainers { - if init.Name == "manage-agent-hostpath-permissions" { - for j, cmd := range ds.Spec.Template.Spec.InitContainers[i].Command { - updatedCmd := strings.Replace( - cmd, - "/var/lib/elastic-agent/default/elastic-agent/state", - fmt.Sprintf("/var/lib/elastic-agent/%s/elastic-agent-%s/state", namespace, suffix), - 1, - ) - ds.Spec.Template.Spec.InitContainers[i].Command[j] = strings.Replace( - updatedCmd, - "/var/lib/elastic-agent/default/fleet-server/state", - fmt.Sprintf("/var/lib/elastic-agent/%s/fleet-server-%s/state", namespace, suffix), - 1, - ) - } - } - } -} - // sortBuilders mutates the given builder slice to sort them by test priority: // Elasticsearch > Kibana > APMServer > Enterprise Search > Beats // The underlying goal is, for example, to ensure Elasticsearch is available before we start testing Beats. @@ -498,48 +470,6 @@ func tweakConfigLiterals(config *commonv1.Config, suffix string, namespace strin } } - fleetOutputsKey := "xpack.fleet.outputs" - - // This is only used when testing Agent+Fleet running as non-root. (config/recipes/elastic-agent/fleet-kubernetes-integration-nonroot.yaml) - // - // Adjust the Kibana's spec.config.xpack.fleet.outputs section to both - // 1. Point to the valid Elasticsearch instance with suffix + namespace being random - // 2. Point to the valid mounted Elasticsearch CA with a random suffix + namespace in the mount path. - if untypedOutputs, ok := data[fleetOutputsKey]; ok { //nolint:nestif - if untypedXpackOutputsSlice, ok := untypedOutputs.([]interface{}); ok { - for _, untypedOutputMap := range untypedXpackOutputsSlice { - if outputMap, ok := untypedOutputMap.(map[string]interface{}); ok { - if outputMap["id"] == "eck-fleet-agent-output-elasticsearch" { - if outputSlice, ok := outputMap["hosts"].([]interface{}); ok { - for j, untypedHost := range outputSlice { - if host, ok := untypedHost.(string); ok { - outputSlice[j] = strings.ReplaceAll( - host, - "elasticsearch-es-http.default", - fmt.Sprintf("elasticsearch-%s-es-http.%s", suffix, namespace), - ) - } - } - } - if untypedSSL, ok := outputMap["ssl"].(map[string]interface{}); ok { - if untypedCAs, ok := untypedSSL["certificate_authorities"].([]interface{}); ok { - for k, untypedCA := range untypedCAs { - if ca, ok := untypedCA.(string); ok { - untypedCAs[k] = strings.ReplaceAll( - ca, - "elasticsearch-association/default/elasticsearch/", - fmt.Sprintf("elasticsearch-association/%s/elasticsearch-%s/", namespace, suffix), - ) - } - } - } - } - } - } - } - } - } - return data } From c26e9fd5f3c978added3ee93a7bc649f8e185198 Mon Sep 17 00:00:00 2001 From: Michael Montgomery Date: Mon, 24 Nov 2025 15:52:08 -0600 Subject: [PATCH 2/4] Remove recipe Signed-off-by: Michael Montgomery --- .../fleet-kubernetes-integration-nonroot.yaml | 325 ------------------ 1 file changed, 325 deletions(-) delete mode 100644 config/recipes/elastic-agent/fleet-kubernetes-integration-nonroot.yaml diff --git a/config/recipes/elastic-agent/fleet-kubernetes-integration-nonroot.yaml b/config/recipes/elastic-agent/fleet-kubernetes-integration-nonroot.yaml deleted file mode 100644 index 2c0fe09fbd..0000000000 --- a/config/recipes/elastic-agent/fleet-kubernetes-integration-nonroot.yaml +++ /dev/null @@ -1,325 +0,0 @@ ---- -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: manage-agent-hostpath-permissions -spec: - selector: - matchLabels: - name: manage-agent-hostpath-permissions - template: - metadata: - labels: - name: manage-agent-hostpath-permissions - spec: - # This is only required when running in an SELinux-enabled/OpenShift environment. - # Ensure this user has been added to the privileged scc in the correct namespace. - # oc adm policy add-scc-to-user privileged -z elastic-agent -n elastic-apps - # serviceAccountName: elastic-agent - volumes: - - hostPath: - path: /var/lib/elastic-agent - type: DirectoryOrCreate - name: "agent-data" - initContainers: - - name: manage-agent-hostpath-permissions - # UBI is only required when needing the `chcon` binary when running - # in an SELinux-enabled/OpenShift environment. If that - # is not required then the following smaller image can be used instead: - # image: registry.access.redhat.com/ubi9/ubi-minimal:latest - image: docker.io/bash:5.2.15 - resources: - limits: - cpu: 100m - memory: 32Mi - securityContext: - # privileged is only required when running in an SELinux-enabled/OpenShift environment. - # privileged: true - runAsUser: 0 - volumeMounts: - - mountPath: /var/lib/elastic-agent - name: agent-data - command: - - 'bash' - - '-e' - - '-c' - - |- - # Adjust this be /var/lib/elastic-agent/YOUR-NAMESPACE/YOUR-AGENT-NAME/state - # Multiple directories are supported for the fleet-server + agent use case. - dirs=( - "/var/lib/elastic-agent/default/elastic-agent/state" - "/var/lib/elastic-agent/default/fleet-server/state" - ) - for dir in ${dirs[@]}; do - mkdir -p "${dir}" - # chcon is only required when running an SELinux-enabled/OpenShift environment. - # chcon -Rt svirt_sandbox_file_t "${dir}" - chmod g+rw "${dir}" - chgrp 1000 "${dir}" - if [ -n "$(ls -A ${dir} 2>/dev/null)" ] - then - chgrp 1000 "${dir}"/* - chmod g+rw "${dir}"/* - fi - done - containers: - - name: pause - image: gcr.io/google-containers/pause-amd64:3.1 ---- -apiVersion: kibana.k8s.elastic.co/v1 -kind: Kibana -metadata: - name: kibana -spec: - version: 9.2.0 - count: 1 - elasticsearchRef: - name: elasticsearch - config: - xpack.fleet.agents.fleet_server.hosts: ["https://fleet-server-agent-http.default.svc:8220"] - xpack.fleet.outputs: - - id: eck-fleet-agent-output-elasticsearch - is_default: true - name: eck-elasticsearch - type: elasticsearch - hosts: ["https://elasticsearch-es-http.default.svc:9200"] - ssl: - certificate_authorities: ["/mnt/elastic-internal/elasticsearch-association/default/elasticsearch/certs/ca.crt"] - xpack.fleet.packages: - - name: system - version: latest - - name: elastic_agent - version: latest - - name: fleet_server - version: latest - - name: kubernetes - version: latest - xpack.fleet.agentPolicies: - - name: Fleet Server on ECK policy - id: eck-fleet-server - namespace: default - is_managed: true - monitoring_enabled: - - logs - - metrics - unenroll_timeout: 900 - package_policies: - - name: fleet_server-1 - id: fleet_server-1 - package: - name: fleet_server - - name: Elastic Agent on ECK policy - id: eck-agent - namespace: default - is_managed: true - monitoring_enabled: - - logs - - metrics - unenroll_timeout: 900 - package_policies: - - package: - name: system - name: system-1 - - package: - name: kubernetes - name: kubernetes-1 ---- -apiVersion: elasticsearch.k8s.elastic.co/v1 -kind: Elasticsearch -metadata: - name: elasticsearch -spec: - version: 9.2.0 - nodeSets: - - name: default - count: 3 - config: - node.store.allow_mmap: false ---- -apiVersion: agent.k8s.elastic.co/v1alpha1 -kind: Agent -metadata: - name: fleet-server -spec: - version: 9.2.0 - kibanaRef: - name: kibana - elasticsearchRefs: - - name: elasticsearch - mode: fleet - fleetServerEnabled: true - policyID: eck-fleet-server - deployment: - replicas: 1 - podTemplate: - spec: - serviceAccountName: fleet-server - automountServiceAccountToken: true ---- -apiVersion: agent.k8s.elastic.co/v1alpha1 -kind: Agent -metadata: - name: elastic-agent -spec: - version: 9.2.0 - kibanaRef: - name: kibana - fleetServerRef: - name: fleet-server - mode: fleet - policyID: eck-agent - daemonSet: - podTemplate: - spec: - hostNetwork: true - dnsPolicy: ClusterFirstWithHostNet - serviceAccountName: elastic-agent - automountServiceAccountToken: true ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: fleet-server -rules: -- apiGroups: [""] - resources: - - pods - - namespaces - - nodes - verbs: - - get - - watch - - list -- apiGroups: ["apps"] - resources: - - replicasets - verbs: - - get - - watch - - list -- apiGroups: ["batch"] - resources: - - jobs - verbs: - - get - - watch - - list -- apiGroups: ["coordination.k8s.io"] - resources: - - leases - verbs: - - get - - create - - update ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: fleet-server ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: fleet-server -subjects: -- kind: ServiceAccount - name: fleet-server - namespace: default -roleRef: - kind: ClusterRole - name: fleet-server - apiGroup: rbac.authorization.k8s.io ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: elastic-agent -rules: -- apiGroups: [""] - resources: - - pods - - nodes - - namespaces - - events - - services - - configmaps - verbs: - - get - - watch - - list -- apiGroups: ["coordination.k8s.io"] - resources: - - leases - verbs: - - get - - create - - update -- nonResourceURLs: - - "/metrics" - verbs: - - get -- apiGroups: ["extensions"] - resources: - - replicasets - verbs: - - "get" - - "list" - - "watch" -- apiGroups: - - "apps" - resources: - - statefulsets - - deployments - - replicasets - - daemonsets - verbs: - - "get" - - "list" - - "watch" -- apiGroups: - - "" - resources: - - nodes/stats - verbs: - - get -- nonResourceURLs: - - "/metrics" - verbs: - - get -- apiGroups: - - "batch" - resources: - - jobs - - cronjobs - verbs: - - "get" - - "list" - - "watch" -- apiGroups: - - "storage.k8s.io" - resources: - - storageclasses - verbs: - - "get" - - "list" - - "watch" ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: elastic-agent - namespace: default ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: elastic-agent -subjects: -- kind: ServiceAccount - name: elastic-agent - namespace: default -roleRef: - kind: ClusterRole - name: elastic-agent - apiGroup: rbac.authorization.k8s.io -... From 4c26d8071a81887cbbb38536ff15bc6a292e9111 Mon Sep 17 00:00:00 2001 From: Michael Montgomery Date: Wed, 26 Nov 2025 09:53:08 -0600 Subject: [PATCH 3/4] Add additional notes to the example and add back the recipe. Signed-off-by: Michael Montgomery --- config/recipes/elastic-agent/README.asciidoc | 4 + .../fleet-kubernetes-integration-nonroot.yaml | 328 ++++++++++++++++++ 2 files changed, 332 insertions(+) create mode 100644 config/recipes/elastic-agent/fleet-kubernetes-integration-nonroot.yaml diff --git a/config/recipes/elastic-agent/README.asciidoc b/config/recipes/elastic-agent/README.asciidoc index 8a45b3f980..a83b769fed 100644 --- a/config/recipes/elastic-agent/README.asciidoc +++ b/config/recipes/elastic-agent/README.asciidoc @@ -31,6 +31,10 @@ Deploys two Elasticsearch clusters and two Kibana instances together with single Deploys Elastic Agent as a DaemonSet in Fleet mode with System and Kubernetes integrations enabled. System integration collects syslog logs, auth logs and system metrics (for CPU, I/O, filesystem, memory, network, process and others). Kubernetes integrations collects API server, Container, Event, Node, Pod, Volume and system metrics. +===== System and Kubernetes integrations running as non-root - `fleet-kubernetes-integration-nonroot.yaml` + +The provided example is functionally identical to the previous section but runs the Elastic Agent processes (both the Elastic Agent running as the Fleet server and the Elastic Agent connected to Fleet) as a non-root user by utilizing a DaemonSet to ensure directory and file permissions. *Note* This is only required when Elastic Agent is < 8.16.0. Also the DaemonSet itself must run as root to set up permissions and ECK >= 2.10.0 is required. + ===== Custom logs integration with autodiscover - `fleet-custom-logs-integration.yaml` Deploys Elastic Agent as a DaemonSet in Fleet mode with Custom Logs integration enabled. Collects logs from all Pods in the `default` namespace using autodiscover feature. diff --git a/config/recipes/elastic-agent/fleet-kubernetes-integration-nonroot.yaml b/config/recipes/elastic-agent/fleet-kubernetes-integration-nonroot.yaml new file mode 100644 index 0000000000..511dfb33fc --- /dev/null +++ b/config/recipes/elastic-agent/fleet-kubernetes-integration-nonroot.yaml @@ -0,0 +1,328 @@ +--- +# This example only applies to Elastic Agent versions < v8.16.0. +# Since Elastic Agent v8.16.0, the `runAsUser: 0` is not needed +# as Agent changes the ownership of the volumes mounts to the container user id. +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: manage-agent-hostpath-permissions +spec: + selector: + matchLabels: + name: manage-agent-hostpath-permissions + template: + metadata: + labels: + name: manage-agent-hostpath-permissions + spec: + # This is only required when running in an SELinux-enabled/OpenShift environment. + # Ensure this user has been added to the privileged scc in the correct namespace. + # oc adm policy add-scc-to-user privileged -z elastic-agent -n elastic-apps + # serviceAccountName: elastic-agent + volumes: + - hostPath: + path: /var/lib/elastic-agent + type: DirectoryOrCreate + name: "agent-data" + initContainers: + - name: manage-agent-hostpath-permissions + # UBI is only required when needing the `chcon` binary when running + # in an SELinux-enabled/OpenShift environment. If that + # is not required then the following smaller image can be used instead: + # image: registry.access.redhat.com/ubi9/ubi-minimal:latest + image: docker.io/bash:5.2.15 + resources: + limits: + cpu: 100m + memory: 32Mi + securityContext: + # privileged is only required when running in an SELinux-enabled/OpenShift environment. + # privileged: true + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/elastic-agent + name: agent-data + command: + - 'bash' + - '-e' + - '-c' + - |- + # Adjust this be /var/lib/elastic-agent/YOUR-NAMESPACE/YOUR-AGENT-NAME/state + # Multiple directories are supported for the fleet-server + agent use case. + dirs=( + "/var/lib/elastic-agent/default/elastic-agent/state" + "/var/lib/elastic-agent/default/fleet-server/state" + ) + for dir in ${dirs[@]}; do + mkdir -p "${dir}" + # chcon is only required when running an SELinux-enabled/OpenShift environment. + # chcon -Rt svirt_sandbox_file_t "${dir}" + chmod g+rw "${dir}" + chgrp 1000 "${dir}" + if [ -n "$(ls -A ${dir} 2>/dev/null)" ] + then + chgrp 1000 "${dir}"/* + chmod g+rw "${dir}"/* + fi + done + containers: + - name: pause + image: gcr.io/google-containers/pause-amd64:3.1 +--- +apiVersion: kibana.k8s.elastic.co/v1 +kind: Kibana +metadata: + name: kibana +spec: + version: 9.2.0 + count: 1 + elasticsearchRef: + name: elasticsearch + config: + xpack.fleet.agents.fleet_server.hosts: ["https://fleet-server-agent-http.default.svc:8220"] + xpack.fleet.outputs: + - id: eck-fleet-agent-output-elasticsearch + is_default: true + name: eck-elasticsearch + type: elasticsearch + hosts: ["https://elasticsearch-es-http.default.svc:9200"] + ssl: + certificate_authorities: ["/mnt/elastic-internal/elasticsearch-association/default/elasticsearch/certs/ca.crt"] + xpack.fleet.packages: + - name: system + version: latest + - name: elastic_agent + version: latest + - name: fleet_server + version: latest + - name: kubernetes + version: latest + xpack.fleet.agentPolicies: + - name: Fleet Server on ECK policy + id: eck-fleet-server + namespace: default + is_managed: true + monitoring_enabled: + - logs + - metrics + unenroll_timeout: 900 + package_policies: + - name: fleet_server-1 + id: fleet_server-1 + package: + name: fleet_server + - name: Elastic Agent on ECK policy + id: eck-agent + namespace: default + is_managed: true + monitoring_enabled: + - logs + - metrics + unenroll_timeout: 900 + package_policies: + - package: + name: system + name: system-1 + - package: + name: kubernetes + name: kubernetes-1 +--- +apiVersion: elasticsearch.k8s.elastic.co/v1 +kind: Elasticsearch +metadata: + name: elasticsearch +spec: + version: 9.2.0 + nodeSets: + - name: default + count: 3 + config: + node.store.allow_mmap: false +--- +apiVersion: agent.k8s.elastic.co/v1alpha1 +kind: Agent +metadata: + name: fleet-server +spec: + version: 9.2.0 + kibanaRef: + name: kibana + elasticsearchRefs: + - name: elasticsearch + mode: fleet + fleetServerEnabled: true + policyID: eck-fleet-server + deployment: + replicas: 1 + podTemplate: + spec: + serviceAccountName: fleet-server + automountServiceAccountToken: true +--- +apiVersion: agent.k8s.elastic.co/v1alpha1 +kind: Agent +metadata: + name: elastic-agent +spec: + version: 9.2.0 + kibanaRef: + name: kibana + fleetServerRef: + name: fleet-server + mode: fleet + policyID: eck-agent + daemonSet: + podTemplate: + spec: + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + serviceAccountName: elastic-agent + automountServiceAccountToken: true +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: fleet-server +rules: +- apiGroups: [""] + resources: + - pods + - namespaces + - nodes + verbs: + - get + - watch + - list +- apiGroups: ["apps"] + resources: + - replicasets + verbs: + - get + - watch + - list +- apiGroups: ["batch"] + resources: + - jobs + verbs: + - get + - watch + - list +- apiGroups: ["coordination.k8s.io"] + resources: + - leases + verbs: + - get + - create + - update +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: fleet-server +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: fleet-server +subjects: +- kind: ServiceAccount + name: fleet-server + namespace: default +roleRef: + kind: ClusterRole + name: fleet-server + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: elastic-agent +rules: +- apiGroups: [""] + resources: + - pods + - nodes + - namespaces + - events + - services + - configmaps + verbs: + - get + - watch + - list +- apiGroups: ["coordination.k8s.io"] + resources: + - leases + verbs: + - get + - create + - update +- nonResourceURLs: + - "/metrics" + verbs: + - get +- apiGroups: ["extensions"] + resources: + - replicasets + verbs: + - "get" + - "list" + - "watch" +- apiGroups: + - "apps" + resources: + - statefulsets + - deployments + - replicasets + - daemonsets + verbs: + - "get" + - "list" + - "watch" +- apiGroups: + - "" + resources: + - nodes/stats + verbs: + - get +- nonResourceURLs: + - "/metrics" + verbs: + - get +- apiGroups: + - "batch" + resources: + - jobs + - cronjobs + verbs: + - "get" + - "list" + - "watch" +- apiGroups: + - "storage.k8s.io" + resources: + - storageclasses + verbs: + - "get" + - "list" + - "watch" +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: elastic-agent + namespace: default +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: elastic-agent +subjects: +- kind: ServiceAccount + name: elastic-agent + namespace: default +roleRef: + kind: ClusterRole + name: elastic-agent + apiGroup: rbac.authorization.k8s.io +... From dbd92eec8086e6b88b1904217c5c3d273ac58046 Mon Sep 17 00:00:00 2001 From: Michael Montgomery Date: Mon, 1 Dec 2025 13:42:18 -0600 Subject: [PATCH 4/4] Adjust wording. Signed-off-by: Michael Montgomery --- .../recipes/elastic-agent/fleet-kubernetes-integration.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/recipes/elastic-agent/fleet-kubernetes-integration.yaml b/config/recipes/elastic-agent/fleet-kubernetes-integration.yaml index 6ba84f572e..2bac132bc6 100644 --- a/config/recipes/elastic-agent/fleet-kubernetes-integration.yaml +++ b/config/recipes/elastic-agent/fleet-kubernetes-integration.yaml @@ -81,7 +81,7 @@ spec: serviceAccountName: fleet-server automountServiceAccountToken: true # Since Elastic Agent v8.16.0, the runAsUser: 0 is not needed - # as Agent chowns the data directory to the container user id. + # as Agent changes ownership of the data directory to the container user id. # securityContext: # runAsUser: 0 --- @@ -117,7 +117,7 @@ spec: dnsPolicy: ClusterFirstWithHostNet automountServiceAccountToken: true # Since Elastic Agent v8.16.0, the runAsUser: 0 is not needed - # as Agent chowns the data directory to the container user id. + # as Agent changes ownership of the data directory to the container user id. # securityContext: # runAsUser: 0 ---