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

Helm - allow loading all alloy files in /etc/alloy #1016

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

fculpo
Copy link

@fculpo fculpo commented Jun 11, 2024

PR Description

This PR implements this cli feature: 0b0b4a5

Currently, the chart only allows to load a single alloy file as an entrypoint.
This behaviour, even with modules, makes overrides or unloading components in some clusters difficult when using a common configuration.

This PR enables loading all alloy files in /etc/alloy (a la terraform).
Configmap can then be overridden in some environments/clusters by not loading, adding some files, or only modifying the needed one.

Which issue(s) this PR fixes

Fixes #228

Notes to the Reviewer

PR Checklist

  • CHANGELOG.md updated
  • Documentation added

@CLAassistant
Copy link

CLAassistant commented Jun 11, 2024

CLA assistant check
All committers have signed the CLA.

@fculpo fculpo force-pushed the load-folder branch 3 times, most recently from fa6c9fa to 2558e42 Compare June 11, 2024 07:59
@fculpo
Copy link
Author

fculpo commented Jun 18, 2024

@tpaschalis I updated README with helm-docs.
Sorry, forgot this.

@fculpo
Copy link
Author

fculpo commented Jun 18, 2024

For a full explanation (discussion in Slack: https://grafana.slack.com/archives/C01050C3D8F/p1718700321152549)

This is the jsonnet code deploying Alloy (we use Tanka + Flux)

local fluxcd = import 'fluxcd.libsonnet';
local helmRelease = fluxcd.helmRelease;
local helmRepository = fluxcd.helmRepository;

local k = import 'k.libsonnet';
local configMap = k.core.v1.configMap;
local envVar = k.core.v1.envVar;

local name = 'grafana-alloy';
local namespace = 'grafana-alloy';

{
  _config:: {
    version: '<0.4',
    cluster: error 'cluster required',
    loki_url: 'https://sth/loki/api/v1/push',
    tempo_url: 'https://sth/',
    pyro_url: 'https://sth/',
    values: {
      alloy: {
        stabilityLevel: 'public-preview',
        clustering: {
          enabled: false,
        },
        configMap+: {
          create: false,
          name: $.configMap.metadata.name,
          key: 'config.river', // unneeded with PR
        },
        mounts: {
          varlog: true,
          dockercontainers: true,
          extra: [],
        },
        securityContext: {
          privileged: true,
          runAsNonRoot: false,
        },
        resources: {
          requests: {
            cpu: '10m',
            memory: '256Mi',
          },
          limits: {
            memory: '256Mi',
          },
        },
        extraEnv: [
          envVar.new('CLUSTER', $._config.cluster),
          envVar.new('LOKI_ENDPOINT_URL', $._config.loki_url),
          envVar.new('TEMPO_ENDPOINT_URL', $._config.tempo_url),
          envVar.new('PYRO_ENDPOINT_URL', $._config.pyro_url),
        ],
        envFrom: [
          {
            secretRef: {
              name: name, // ingress authentication
            },
          },
        ],
        extraPorts: [
          {
            name: 'otlp-grpc',
            port: 4317,
            targetPort: 4317,
            protocol: 'TCP',
          },
          {
            name: 'otlp-http',
            port: 4318,
            targetPort: 4318,
            protocol: 'TCP',
          },
        ],
      },
      controller: {
        hostPID: true,  // needed for java profiling
        priorityClassName: (import 'infra/main.libsonnet').priorityClasses.high.metadata.name,
      },
      configReloader: {
        resources: {
          requests: {
            cpu: '10m',
            memory: '100Mi',
          },
          limits: {
            memory: '100Mi',
          },
        },
      },
      service: {
        internalTrafficPolicy: 'Local', // route to local DS pod
      },
      serviceMonitor: {
        enabled: true,
      },
    },
  },

  // we create our configmap with multiples files
  // will be expanded as files in /etc/alloy
  configMap:
    configMap.new(name) +
    configMap.metadata.withNamespace(namespace) +
    configMap.withData({
      'config.alloy': importstr './config/config.alloy',
      'pyroscope.alloy': importstr './config/pyroscope.alloy',
      // this one will be overridden in non basic auth clusters
      'pyroscope-push.alloy': importstr './config/pyroscope-push.alloy',
    }),

  helmRepository:
    helmRepository.new(name) +
    helmRepository.metadata.withNamespace(namespace) +
    helmRepository.spec.withInterval('1h') +
    helmRepository.spec.withUrl('https://grafana.github.io/helm-charts'),

  helmRelease:
    helmRelease.new(name) +
    helmRelease.metadata.withNamespace(namespace) +
    helmRelease.spec.chart.spec.withChart('alloy') +
    helmRelease.spec.chart.spec.withVersion($._config.version) +
    helmRelease.spec.chart.spec.sourceRef.withKind('HelmRepository') +
    helmRelease.spec.chart.spec.sourceRef.withName($.helmRepository.metadata.name) +
    helmRelease.spec.chart.spec.sourceRef.withNamespace($.helmRepository.metadata.namespace) +
    helmRelease.spec.install.withCrds('CreateReplace') +
    helmRelease.spec.upgrade.withCrds('CreateReplace') +
    helmRelease.spec.withInterval('1h0m0s') +
    helmRelease.spec.withValues($._config.values) +
    // will be unneeded after PR is merged
    helmRelease.spec.withPostRenderers([
      helmRelease.spec.postRenderers.kustomize.withPatches([
        // see MR https://github.com/grafana/alloy/pull/1016
        // Seems that modules are not enough in our case
        // We load all river files (like terraform) at once, so that we can override one file easily
        {
          target: {
            version: 'v1',
            kind: 'DaemonSet',
            name: 'grafana-alloy',
          },
          patch: |||
            - op: replace
              path: /spec/template/spec/containers/0/args/1
              value: /etc/alloy  
          |||,
        },
      ]),
    ]),
}

So basically we deploy a configmap containing multiple files in /etc/alloy (standard Alloy Helm Chart usage)

Now the main issue is actually in .alloy files.
For pyroscope for instance (or tempo/loki/..) we need basic auth in write components, except for some clusters.
But I cannot use same write module and programmatically disable basic auth (or did not find how).

So for almost all clusters pyroscope-push.alloy is:

pyroscope.write "grafana" {
  external_labels = {
		cluster = env("CLUSTER"),
	}
  endpoint {
    url = env("PYRO_ENDPOINT_URL")
    basic_auth {
			username = "pyroscope"
			password = env("PYRO_API_KEY")
		}
  }
}

But for some others I want to push via internal service, not over ingress, hence without auth.

pyroscope.write "grafana" {
  external_labels = {
		cluster = env("CLUSTER"),
	}
  endpoint {
    url = env("PYRO_ENDPOINT_URL")
  }
}

In this particular environment, I then just have to override pyroscope-push.alloyand everything will work nicely.

Same applies to Loki/Tempo/possibly Mimir if you use Alloy for collection.

@fculpo
Copy link
Author

fculpo commented Jun 24, 2024

Basically, this PR tries to achieve what the meta k8s monitoring helm chart does: https://github.com/grafana/k8s-monitoring-helm/blob/2e2392002d17c98c100ade51e2ecaf2fa3e70a58/charts/k8s-monitoring/templates/alloy_config/_logs_service_loki.alloy.txt#L11

If/else on non "if-able" blocks

@fculpo
Copy link
Author

fculpo commented Jun 28, 2024

Opened proposal: #1176

Copy link
Contributor

This PR has not had any activity in the past 30 days, so the needs-attention label has been added to it.
If you do not have enough time to follow up on this PR or you think it's no longer relevant, consider closing it.
The needs-attention label signals to maintainers that something has fallen through the cracks. No action is needed by you; your PR will be kept open and you do not have to respond to this comment. The label will be removed the next time this job runs if there is new activity.
Thank you for your contributions!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow helm chart to load all river files in volumemount
2 participants