Skip to content

Commit

Permalink
template grafana-agent-config (#273)
Browse files Browse the repository at this point in the history
* template grafana-agent-config

* fix incorrect grafana agent secret namespace

* add common format scraped namespaces
  • Loading branch information
QuentinBisson authored Nov 20, 2024
1 parent b24f44c commit 5319466
Show file tree
Hide file tree
Showing 15 changed files with 375 additions and 185 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- Disable grafana agent usage data reporting.
- Move Grafana-Agent config to a template instead of go structs.

### Fixed

Expand Down
8 changes: 5 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ import (
loggingreconciler "github.com/giantswarm/logging-operator/pkg/logging-reconciler"
"github.com/giantswarm/logging-operator/pkg/reconciler"
agentstoggle "github.com/giantswarm/logging-operator/pkg/resource/agents-toggle"
eventsloggerconfig "github.com/giantswarm/logging-operator/pkg/resource/grafana-agent-config"
eventsloggersecret "github.com/giantswarm/logging-operator/pkg/resource/grafana-agent-secret"
eventsloggerconfig "github.com/giantswarm/logging-operator/pkg/resource/events-logger-config"
eventsloggersecret "github.com/giantswarm/logging-operator/pkg/resource/events-logger-secret"
grafanadatasource "github.com/giantswarm/logging-operator/pkg/resource/grafana-datasource"
loggingconfig "github.com/giantswarm/logging-operator/pkg/resource/logging-config"
loggingcredentials "github.com/giantswarm/logging-operator/pkg/resource/logging-credentials"
Expand Down Expand Up @@ -172,11 +172,13 @@ func main() {
}

eventsLoggerConfig := eventsloggerconfig.Reconciler{
Client: mgr.GetClient(),
Client: mgr.GetClient(),
DefaultWorkloadClusterNamespaces: defaultNamespaces,
}

loggedcluster.O.EnableLoggingFlag = enableLogging
loggedcluster.O.LoggingAgent = loggingAgent
loggedcluster.O.KubeEventsLogger = eventsLogger
loggedcluster.O.InstallationName = installationName
loggedcluster.O.InsecureCA = insecureCA
setupLog.Info("Loggedcluster config", "options", loggedcluster.O)
Expand Down
10 changes: 10 additions & 0 deletions pkg/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package common

import (
"context"
"fmt"
"strings"

"github.com/pkg/errors"
netv1 "k8s.io/api/networking/v1"
Expand Down Expand Up @@ -76,3 +78,11 @@ func ReadProxyIngressURL(ctx context.Context, lc loggedcluster.Interface, client

return ingressURL, nil
}

func FormatScrapedNamespaces(lc loggedcluster.Interface, namespaces []string) string {
if IsWorkloadCluster(lc) {
return fmt.Sprintf("[\"%s\"]", strings.Join(namespaces, "\", \""))
}

return "[]"
}
4 changes: 2 additions & 2 deletions pkg/resource/agents-toggle/observability_bundle_configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func GenerateObservabilityBundleConfigMap(ctx context.Context, lc loggedcluster.
// Enforce promtail as logging agent when observability-bundle version < 1.6.0 because this needs alloy 0.4.0.
if observabilityBundleVersion.LT(semver.MustParse("1.6.0")) && lc.GetLoggingAgent() == common.LoggingAgentAlloy {
logger := log.FromContext(ctx)
logger.Info("Logging agent is not supported by observability bundle, using promtail instead.", "observability-bundle-version", observabilityBundleVersion, "logging-agent", lc.GetLoggingAgent())
logger.Info("Alloy logging agent is not supported by observability bundle, using promtail instead.", "observability-bundle-version", observabilityBundleVersion, "logging-agent", lc.GetLoggingAgent())
lc.SetLoggingAgent(common.LoggingAgentPromtail)
}

Expand All @@ -62,7 +62,7 @@ func GenerateObservabilityBundleConfigMap(ctx context.Context, lc loggedcluster.
// Enforce grafana-agent as events logger when observability-bundle version < 1.9.0 because this needs alloy 0.7.0.
if observabilityBundleVersion.LT(semver.MustParse("1.9.0")) && lc.GetKubeEventsLogger() == common.EventsLoggerAlloy {
logger := log.FromContext(ctx)
logger.Info("Events logger is not supported by observability bundle, using grafana-agent instead.", "observability-bundle-version", observabilityBundleVersion, "events-logger", lc.GetKubeEventsLogger())
logger.Info("Alloy events logger is not supported by observability bundle, using grafana-agent instead.", "observability-bundle-version", observabilityBundleVersion, "events-logger", lc.GetKubeEventsLogger())
lc.SetKubeEventsLogger(common.EventsLoggerGrafanaAgent)
}

Expand Down
98 changes: 98 additions & 0 deletions pkg/resource/events-logger-config/grafana-agent-config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package eventsloggerconfig

import (
"bytes"
_ "embed"
"fmt"
"text/template"

"github.com/Masterminds/sprig/v3"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/giantswarm/logging-operator/pkg/common"
loggedcluster "github.com/giantswarm/logging-operator/pkg/logged-cluster"
)

const (
grafanaAgentConfigName = "grafana-agent-config"
)

var (
//go:embed grafana-agent/events-logger.grafanaagent.template
grafanaAgent string
grafanaAgentTemplate *template.Template

//go:embed grafana-agent/events-logger-config.grafanaagent.yaml.template
grafanaAgentConfig string
grafanaAgentConfigTemplate *template.Template
)

func init() {
grafanaAgentTemplate = template.Must(template.New("events-logger.grafanaagent").Funcs(sprig.FuncMap()).Parse(grafanaAgent))
grafanaAgentConfigTemplate = template.Must(template.New("events-logger-config.grafanaagent.yaml").Funcs(sprig.FuncMap()).Parse(grafanaAgentConfig))
}

// configMeta returns metadata for the grafana-agent-config
func configMeta(lc loggedcluster.Interface) metav1.ObjectMeta {
metadata := metav1.ObjectMeta{
Name: getGrafanaAgentConfigName(lc),
Namespace: lc.GetAppsNamespace(),
Labels: map[string]string{},
}

common.AddCommonLabels(metadata.Labels)
return metadata
}

// generateGrafanaAgentConfig returns a configmap for
// the grafana-agent extra-config
func generateGrafanaAgentConfig(lc loggedcluster.Interface, defaultWorkloadClusterNamespaces []string) (string, error) {
var values bytes.Buffer

grafanaAgentInnerConfig, err := generateGrafanaAgentInnerConfig(lc, defaultWorkloadClusterNamespaces)
if err != nil {
return "", err
}

data := struct {
GrafanaAgentInnerConfig string
}{
GrafanaAgentInnerConfig: grafanaAgentInnerConfig,
}

err = grafanaAgentTemplate.Execute(&values, data)
if err != nil {
return "", err
}

return values.String(), nil
}

func generateGrafanaAgentInnerConfig(lc loggedcluster.Interface, defaultWorkloadClusterNamespaces []string) (string, error) {
var values bytes.Buffer

data := struct {
ClusterID string
Installation string
InsecureSkipVerify string
SecretName string
ScrapedNamespaces string
}{
ClusterID: lc.GetClusterName(),
Installation: lc.GetInstallationName(),
InsecureSkipVerify: fmt.Sprintf("%t", lc.IsInsecureCA()),
SecretName: fmt.Sprintf("%s-%s", lc.GetClusterName(), common.GrafanaAgentExtraSecretName()),
ScrapedNamespaces: common.FormatScrapedNamespaces(lc, defaultWorkloadClusterNamespaces),
}

err := grafanaAgentConfigTemplate.Execute(&values, data)
if err != nil {
return "", err
}

return values.String(), nil
}

func getGrafanaAgentConfigName(lc loggedcluster.Interface) string {
return fmt.Sprintf("%s-%s", lc.GetClusterName(), grafanaAgentConfigName)
}
77 changes: 77 additions & 0 deletions pkg/resource/events-logger-config/grafana-agent-config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package eventsloggerconfig

import (
_ "embed"
"flag"
"os"
"path/filepath"
"testing"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
capi "sigs.k8s.io/cluster-api/api/v1beta1"

"github.com/google/go-cmp/cmp"

loggedcluster "github.com/giantswarm/logging-operator/pkg/logged-cluster"
"github.com/giantswarm/logging-operator/pkg/logged-cluster/capicluster"
)

var (
update = flag.Bool("update", false, "update .golden files")
)

func TestGenerateGrafanaAgentConfig(t *testing.T) {
testCases := []struct {
goldenFile string
defaultNamespaces []string
installationName string
clusterName string
}{
{
goldenFile: "grafana-agent/test/events-logger-config.grafanaagent.MC.yaml",
installationName: "test-installation",
clusterName: "test-installation",
},
{
goldenFile: "grafana-agent/test/events-logger-config.grafanaagent.WC.yaml",
installationName: "test-installation",
clusterName: "test-cluster",
},
}

for _, tc := range testCases {
t.Run(filepath.Base(tc.goldenFile), func(t *testing.T) {
golden, err := os.ReadFile(tc.goldenFile)
if err != nil {
t.Fatalf("Failed to read golden file: %v", err)
}

loggedCluster := &capicluster.Object{
Object: &capi.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: tc.clusterName,
},
},
Options: loggedcluster.Options{
InstallationName: tc.installationName,
},
}

config, err := generateGrafanaAgentConfig(loggedCluster, []string{"kube-system", "giantswarm"})
if err != nil {
t.Fatalf("Failed to generate grafana-agent config: %v", err)
}

if string(golden) != config {
t.Logf("Generated config differs from %s, diff:\n%s", tc.goldenFile, cmp.Diff(string(golden), config))
t.Fail()
if *update {
//nolint:gosec
if err := os.WriteFile(tc.goldenFile, []byte(config), 0644); err != nil {
t.Fatalf("Failed to update golden file: %v", err)
}
}
}
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
logging {
level = "info"
format = "logfmt"
}

loki.source.kubernetes_events "local" {
namespaces = {{ .ScrapedNamespaces }}
forward_to = [loki.write.default.receiver]
}

remote.kubernetes.secret "credentials" {
namespace = "kube-system"
name = "{{ .SecretName }}"
}

loki.write "default" {
endpoint {
url = nonsensitive(remote.kubernetes.secret.credentials.data["logging-url"])
tenant_id = nonsensitive(remote.kubernetes.secret.credentials.data["logging-tenant-id"])

basic_auth {
username = nonsensitive(remote.kubernetes.secret.credentials.data["logging-username"])
password = remote.kubernetes.secret.credentials.data["logging-password"]
}

tls_config {
insecure_skip_verify = {{ .InsecureSkipVerify }}
}
}
external_labels = {
installation = "{{ .Installation }}",
cluster_id = "{{ .ClusterID }}",
scrape_job = "kubernetes-events",
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# This file was generated by logging-operator.
# It configures the Grafana-agent to be used as events logger.
# - configMap is generated from events-logger.grafanaagent.template and passed as a string
# here and will be created by Grafana-agent's chart.
# - Grafana-agent runs as a deployment, with only 1 replica.
grafana-agent:
agent:
configMap:
content: |-
{{- .GrafanaAgentInnerConfig | nindent 8 }}
extraArgs:
- --disable-reporting
controller:
replicas: 1
type: deployment
crds:
create: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# This file was generated by logging-operator.
# It configures the Grafana-agent to be used as events logger.
# - configMap is generated from events-logger.grafanaagent.template and passed as a string
# here and will be created by Grafana-agent's chart.
# - Grafana-agent runs as a deployment, with only 1 replica.
grafana-agent:
agent:
configMap:
content: |-
logging {
level = "info"
format = "logfmt"
}
loki.source.kubernetes_events "local" {
namespaces = []
forward_to = [loki.write.default.receiver]
}
remote.kubernetes.secret "credentials" {
namespace = "kube-system"
name = "test-installation-grafana-agent-secret"
}
loki.write "default" {
endpoint {
url = nonsensitive(remote.kubernetes.secret.credentials.data["logging-url"])
tenant_id = nonsensitive(remote.kubernetes.secret.credentials.data["logging-tenant-id"])
basic_auth {
username = nonsensitive(remote.kubernetes.secret.credentials.data["logging-username"])
password = remote.kubernetes.secret.credentials.data["logging-password"]
}
tls_config {
insecure_skip_verify = false
}
}
external_labels = {
installation = "test-installation",
cluster_id = "test-installation",
scrape_job = "kubernetes-events",
}
}
extraArgs:
- --disable-reporting
controller:
replicas: 1
type: deployment
crds:
create: false
Loading

0 comments on commit 5319466

Please sign in to comment.