Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[k8s] embed hints inputs in agent container image #6381

Merged
merged 2 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Kind can be one of:
# - breaking-change: a change to previously-documented behavior
# - deprecation: functionality that is being removed in a later release
# - bug-fix: fixes a problem in a previous version
# - enhancement: extends functionality but does not break or fix existing behavior
# - feature: new functionality
# - known-issue: problems that we are aware of in a given version
# - security: impacts on the security of a product or a user’s deployment.
# - upgrade: important information for someone upgrading from a prior version
# - other: does not fit into any of the other categories
kind: enhancement

# Change summary; a 80ish characters long description of the change.
summary: Embed hints-based inputs in the Elastic Agent container image.

# Long description; in case the summary is not enough to describe the change
# this field accommodates a description without length limits.
# NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment.
description: This change includes the addition of hints-based inputs directly within the Elastic Agent container image, enabling streamlined configurations for input discovery when deployed in containerized environments.

# Affected component; usually one of "elastic-agent", "fleet-server", "filebeat", "metricbeat", "auditbeat", "all", etc.
component: elastic-agent

# PR URL; optional; the PR number that added the changeset.
# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added.
# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number.
# Please provide it if you are adding a fragment for a different PR.
pr: https://github.com/elastic/elastic-agent/pull/6381

# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of).
# If not present is automatically filled by the tooling with the issue linked to the PR number.
issue: https://github.com/elastic/elastic-agent/issues/5661
Original file line number Diff line number Diff line change
Expand Up @@ -1142,36 +1142,13 @@ spec:
- mountPath: /hostfs/var/lib
name: var-lib
readOnly: true
- mountPath: /usr/share/elastic-agent/state/inputs.d
name: external-inputs
- mountPath: /usr/share/elastic-agent/state
name: agent-data
- mountPath: /etc/elastic-agent/agent.yml
name: config
readOnly: true
subPath: agent.yml
dnsPolicy: ClusterFirstWithHostNet
initContainers:
- args:
- -c
- mkdir -p /etc/elastic-agent/inputs.d && mkdir -p /etc/elastic-agent/inputs.d
&& wget -O - https://github.com/elastic/elastic-agent/archive/v9.0.0.tar.gz
| tar xz -C /etc/elastic-agent/inputs.d --strip=5 "elastic-agent-9.0.0/deploy/kubernetes/elastic-agent-standalone/templates.d"
command:
- sh
image: busybox:1.36.1
name: k8s-templates-downloader
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
runAsGroup: 1000
runAsUser: 1000
volumeMounts:
- mountPath: /etc/elastic-agent/inputs.d
name: external-inputs
nodeSelector:
kubernetes.io/os: linux
serviceAccountName: agent-pernode-example
Expand All @@ -1194,8 +1171,6 @@ spec:
- hostPath:
path: /var/lib
name: var-lib
- emptyDir: {}
name: external-inputs
- hostPath:
path: /etc/elastic-agent/default/agent-pernode-example/state
type: DirectoryOrCreate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1158,36 +1158,13 @@ spec:
- mountPath: /hostfs/var/lib
name: var-lib
readOnly: true
- mountPath: /usr/share/elastic-agent/state/inputs.d
name: external-inputs
- mountPath: /usr/share/elastic-agent/state
name: agent-data
- mountPath: /etc/elastic-agent/agent.yml
name: config
readOnly: true
subPath: agent.yml
dnsPolicy: ClusterFirstWithHostNet
initContainers:
- args:
- -c
- mkdir -p /etc/elastic-agent/inputs.d && mkdir -p /etc/elastic-agent/inputs.d
&& wget -O - https://github.com/elastic/elastic-agent/archive/v9.0.0.tar.gz
| tar xz -C /etc/elastic-agent/inputs.d --strip=5 "elastic-agent-9.0.0/deploy/kubernetes/elastic-agent-standalone/templates.d"
command:
- sh
image: busybox:1.36.1
name: k8s-templates-downloader
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
runAsGroup: 1000
runAsUser: 1000
volumeMounts:
- mountPath: /etc/elastic-agent/inputs.d
name: external-inputs
nodeSelector:
kubernetes.io/os: linux
serviceAccountName: agent-pernode-example
Expand All @@ -1210,8 +1187,6 @@ spec:
- hostPath:
path: /var/lib
name: var-lib
- emptyDir: {}
name: external-inputs
- hostPath:
path: /etc/elastic-agent/default/agent-pernode-example/state
type: DirectoryOrCreate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
{{- include "elasticagent.kubernetes.config.state.statefulsets.init" $ -}}
{{- include "elasticagent.kubernetes.config.state.storageclasses.init" $ -}}
{{- include "elasticagent.kubernetes.config.kube_controller.init" $ -}}
{{- include "elasticagent.kubernetes.config.hints.init" $ -}}
{{- include "elasticagent.kubernetes.config.audit_logs.init" $ -}}
{{- include "elasticagent.kubernetes.config.container_logs.init" $ -}}
{{- include "elasticagent.kubernetes.config.kubelet.containers.init" $ -}}
Expand All @@ -28,4 +27,4 @@
{{- include "elasticagent.kubernetes.config.kube_proxy.init" $ -}}
{{- include "elasticagent.kubernetes.config.kube_scheduler.init" $ -}}
{{- end -}}
{{- end -}}
{{- end -}}
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
{{- define "elasticagent.kubernetes.config.hints.init" -}}
{{- if eq $.Values.kubernetes.hints.enabled true -}}
{{- $preset := $.Values.agent.presets.perNode -}}
{{- include "elasticagent.preset.applyOnce" (list $ $preset "elasticagent.kubernetes.pernode.preset") -}}
{{- end -}}
{{- end -}}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
{{- include "elasticagent.preset.mutate.volumes" (list $ $.Values.agent.presets.perNode "elasticagent.kubernetes.pernode.preset.volumes") -}}
{{- include "elasticagent.preset.mutate.outputs.byname" (list $ $.Values.agent.presets.perNode $.Values.kubernetes.output)}}
{{- if eq $.Values.kubernetes.hints.enabled true -}}
{{- include "elasticagent.preset.mutate.initcontainers" (list $ $.Values.agent.presets.perNode "elasticagent.kubernetes.pernode.preset.initcontainers") -}}
{{- include "elasticagent.preset.mutate.providers.kubernetes.hints" (list $ $.Values.agent.presets.perNode "elasticagent.kubernetes.pernode.preset.providers.kubernetes.hints") -}}
{{- end -}}
{{- if or (eq $.Values.kubernetes.scheduler.enabled true) (eq $.Values.kubernetes.controller_manager.enabled true) -}}
Expand Down Expand Up @@ -37,10 +36,6 @@ extraVolumeMounts:
- name: var-lib
mountPath: /hostfs/var/lib
readOnly: true
{{- if eq $.Values.kubernetes.hints.enabled true }}
- name: external-inputs
mountPath: /usr/share/elastic-agent/state/inputs.d
{{- end }}
{{- end -}}

{{- define "elasticagent.kubernetes.pernode.preset.volumes" -}}
Expand All @@ -63,34 +58,6 @@ extraVolumes:
- name: var-lib
hostPath:
path: /var/lib
{{- if eq $.Values.kubernetes.hints.enabled true }}
- name: external-inputs
emptyDir: {}
{{- end }}
{{- end -}}

{{- define "elasticagent.kubernetes.pernode.preset.initcontainers" -}}
initContainers:
- name: k8s-templates-downloader
image: busybox:1.36.1
securityContext:
allowPrivilegeEscalation: false
privileged: false
runAsUser: 1000
runAsGroup: 1000
capabilities:
drop:
- ALL
command: [ 'sh' ]
args:
- -c
- >-
mkdir -p /etc/elastic-agent/inputs.d &&
mkdir -p /etc/elastic-agent/inputs.d &&
wget -O - https://github.com/elastic/elastic-agent/archive/v{{$.Values.agent.version}}.tar.gz | tar xz -C /etc/elastic-agent/inputs.d --strip=5 "elastic-agent-{{$.Values.agent.version}}/deploy/kubernetes/elastic-agent-standalone/templates.d"
volumeMounts:
- name: external-inputs
mountPath: /etc/elastic-agent/inputs.d
{{- end -}}

{{- define "elasticagent.kubernetes.pernode.preset.providers.kubernetes.hints" -}}
Expand Down
35 changes: 26 additions & 9 deletions dev-tools/packaging/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ const (
)

var (
excludedPathsPattern = regexp.MustCompile(`node_modules`)
configFilePattern = regexp.MustCompile(`.*beat\.spec.yml$|.*beat\.yml$|apm-server\.yml|elastic-agent\.yml$$`)
manifestFilePattern = regexp.MustCompile(`manifest.yml`)
modulesDirPattern = regexp.MustCompile(`module/.+`)
modulesDDirPattern = regexp.MustCompile(`modules.d/$`)
modulesDFilePattern = regexp.MustCompile(`modules.d/.+`)
monitorsDFilePattern = regexp.MustCompile(`monitors.d/.+`)
systemdUnitFilePattern = regexp.MustCompile(`/lib/systemd/system/.*\.service`)
excludedPathsPattern = regexp.MustCompile(`node_modules`)
configFilePattern = regexp.MustCompile(`.*beat\.spec.yml$|.*beat\.yml$|apm-server\.yml|elastic-agent\.yml$$`)
manifestFilePattern = regexp.MustCompile(`manifest.yml`)
modulesDirPattern = regexp.MustCompile(`module/.+`)
modulesDDirPattern = regexp.MustCompile(`modules.d/$`)
modulesDFilePattern = regexp.MustCompile(`modules.d/.+`)
monitorsDFilePattern = regexp.MustCompile(`monitors.d/.+`)
systemdUnitFilePattern = regexp.MustCompile(`/lib/systemd/system/.*\.service`)
hintsInputsDFilePattern = regexp.MustCompile(`usr/share/elastic-agent/hints.inputs.d/.*\.yml`)

licenseFiles = []string{"LICENSE.txt", "NOTICE.txt"}
)
Expand Down Expand Up @@ -297,6 +298,7 @@ func checkDocker(t *testing.T, file string) {
checkManifestPermissionsWithMode(t, p, os.FileMode(0644))
checkModulesPresent(t, "", p)
checkModulesDPresent(t, "", p)
checkHintsInputsD(t, "hints.inputs.d", hintsInputsDFilePattern, p)
checkLicensesPresent(t, "licenses/", p)
}

Expand Down Expand Up @@ -447,6 +449,21 @@ func checkMonitorsDPresent(t *testing.T, prefix string, p *packageFile) {
}
}

func checkHintsInputsD(t *testing.T, name string, r *regexp.Regexp, p *packageFile) {
t.Run(fmt.Sprintf("%s %s contents", p.Name, name), func(t *testing.T) {
total := 0
for _, entry := range p.Contents {
if r.MatchString(entry.File) {
total++
}
}

if total == 0 {
t.Errorf("no hints inputs found under %s", name)
}
})
}

func checkModules(t *testing.T, name, prefix string, r *regexp.Regexp, p *packageFile) {
t.Run(fmt.Sprintf("%s %s contents", p.Name, name), func(t *testing.T) {
minExpectedModules := *minModules
Expand Down Expand Up @@ -711,7 +728,7 @@ func readTarContents(tarName string, data io.Reader) (*packageFile, error) {
File: header.Name,
UID: header.Uid,
GID: header.Gid,
Mode: os.FileMode(header.Mode),
Mode: os.FileMode(header.Mode), //nolint:gosec // Reason: header.Mode should never overflow from int64 -> uint32
}
}

Expand Down
3 changes: 3 additions & 0 deletions dev-tools/packaging/packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ shared:
content: >
{{ commit }}
mode: 0644
'hints.inputs.d':
source: '{{ repo.RootDir }}/deploy/kubernetes/elastic-agent-standalone/templates.d'
mode: 0755

# cloud build to beats-ci repository
- &agent_docker_cloud_spec
Expand Down
8 changes: 7 additions & 1 deletion internal/pkg/agent/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/elastic/elastic-agent/internal/pkg/agent/storage"
"github.com/elastic/elastic-agent/internal/pkg/capabilities"
"github.com/elastic/elastic-agent/internal/pkg/composable"
"github.com/elastic/elastic-agent/internal/pkg/composable/providers/kubernetes"
"github.com/elastic/elastic-agent/internal/pkg/config"
otelmanager "github.com/elastic/elastic-agent/internal/pkg/otel/manager"
"github.com/elastic/elastic-agent/internal/pkg/release"
Expand Down Expand Up @@ -135,7 +136,12 @@ func New(
log.Info("Parsed configuration and determined agent is managed locally")

loader := config.NewLoader(log, paths.ExternalInputs())
discover := config.Discoverer(pathConfigFile, cfg.Settings.Path, paths.ExternalInputs())
rawCfgMap, err := rawConfig.ToMapStr()
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to transform agent configuration into a map: %w", err)
}
discover := config.Discoverer(pathConfigFile, cfg.Settings.Path, paths.ExternalInputs(),
kubernetes.GetHintsInputConfigPath(log, rawCfgMap))
if !cfg.Settings.Reload.Enabled {
log.Debug("Reloading of configuration is off")
configMgr = newOnce(log, discover, loader)
Expand Down
21 changes: 21 additions & 0 deletions internal/pkg/composable/providers/kubernetes/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@
package kubernetes

import (
"errors"
"time"

"github.com/elastic/elastic-agent-autodiscover/kubernetes"
"github.com/elastic/elastic-agent-autodiscover/kubernetes/metadata"
"github.com/elastic/elastic-agent-libs/logp"
"github.com/elastic/elastic-agent/pkg/core/logger"
"github.com/elastic/elastic-agent/pkg/utils"
)

const hintsInputsPathPattern = "/usr/share/elastic-agent/hints.inputs.d/*.yml"
swiatekm marked this conversation as resolved.
Show resolved Hide resolved

// Config for kubernetes provider
type Config struct {
Scope string `config:"scope"`
Expand Down Expand Up @@ -57,6 +62,22 @@ type Enabled struct {
Enabled bool `config:"enabled"`
}

func GetHintsInputConfigPath(log *logger.Logger, agentCfg map[string]interface{}) string {
hintsVal, err := utils.GetNestedMap(agentCfg, "providers", "kubernetes", "hints", "enabled")
if err != nil {
if errors.Is(err, utils.ErrKeyNotFound) {
return ""
}
log.Errorf("error at reading providers.kubernetes.hints.enabled from config: %v", err)
return ""
}
hintsEnabled, ok := hintsVal.(bool)
if !ok || !hintsEnabled {
return ""
}
return hintsInputsPathPattern
}

// InitDefaults initializes the default values for the config.
func (c *Config) InitDefaults() {
c.CleanupTimeout = 60 * time.Second
Expand Down
Loading
Loading