alloy helm

No introduction found. Create it?

More popular helm chart found

alloy from home-operations/charts-mirror/alloy is more popular with 22 repositories.

Install

Install with:

helm repo add grafana oci://ghcr.io/grafana-operator/helm-charts/
helm install alloy grafana/alloy -f values.yaml

Examples

See examples from other people.

Top Repositories (3 out of 17)

NameRepoStarsVersionTimestamp
alloyPumba98/flux2-gitops701.15.04 days ago
alloygabe565/home-ops391.15.012 days ago
alloyanthr76/infra1071.15.013 days ago

Values

See the most popular values for this chart:

KeyTypes
string
string
string
controller.tolerations[].key (1)
node-role.kubernetes.io/control-plane
string
string
string
string
string
string
string
string
string
alloy.configMap.content (13)
logging { level = "info" format = "logfmt" } // Discover only pods running on this node — Alloy runs as a // DaemonSet, so each pod scopes discovery via the K8S_NODE_NAME // env var the chart injects (spec.nodeName). discovery.kubernetes "pods" { role = "pod" selectors { role = "pod" field = "spec.nodeName=" + sys.env("K8S_NODE_NAME") } } // Derive our target label set from pod metadata. // namespace <- __meta_kubernetes_namespace // app <- pod label app.kubernetes.io/name (fallback: `app`) // container <- __meta_kubernetes_pod_container_name // pod <- __meta_kubernetes_pod_name (structured metadata) // node <- __meta_kubernetes_pod_node_name (structured metadata) // // Defaulting to "unknown" for missing namespace/app is done HERE // (via an empty-match relabel rule), NOT in loki.process. Reason: // loki.process stages operate on the per-entry `extracted` map, // which starts empty for each log line and is NOT seeded from the // incoming stream labels. If we ran `stage.template { source = // "namespace" ... else "unknown" }` there, .Value would always be // empty, template would always write "unknown" into extracted, and // the subsequent `stage.labels { namespace = "" }` would promote // that "unknown" back over the good stream label from discovery. // (See labels.go processLabelsConfigs — it reads only from // extracted, never from labels.) This exact mistake was the root // cause of the LokiIngestionDiscardsHigh flapping fixed by #3395. discovery.relabel "pod_logs" { targets = discovery.kubernetes.pods.targets rule { source_labels = ["__meta_kubernetes_namespace"] target_label = "namespace" } // Default namespace to "unknown" if somehow empty (edge-case AC). rule { source_labels = ["namespace"] regex = "^quot; target_label = "namespace" replacement = "unknown" } // Preferred workload label. rule { source_labels = ["__meta_kubernetes_pod_label_app_kubernetes_io_name"] target_label = "app" } // Fallback: bare `app` label (older charts / hand-written manifests). rule { source_labels = ["app", "__meta_kubernetes_pod_label_app"] separator = ";" regex = "^;(.+)quot; target_label = "app" replacement = "$1" } // Default app to "unknown" if no workload label is set at all // (edge-case AC — never drop the line). rule { source_labels = ["app"] regex = "^quot; target_label = "app" replacement = "unknown" } rule { source_labels = ["__meta_kubernetes_pod_container_name"] target_label = "container" } rule { source_labels = ["__meta_kubernetes_pod_name"] target_label = "pod" } rule { source_labels = ["__meta_kubernetes_pod_node_name"] target_label = "node" } // Log files of the container: /var/log/pods/<namespace>_<pod>_<uid>/ // <container>/<restart count>.log. The glob does not match a // rotated file (0.log.20261030-043403) or a compressed file // (.gz), so Alloy does not read a rotated file a second time. rule { source_labels = ["__meta_kubernetes_pod_uid", "__meta_kubernetes_pod_container_name"] separator = "/" target_label = "__path__" replacement = "/var/log/pods/*$1/*.log" } // The log directory of a static pod (kube-vip) has the config // hash in place of the pod UID. The UID of its mirror pod does // not match a directory. rule { source_labels = ["__meta_kubernetes_pod_annotationpresent_kubernetes_io_config_hash", "__meta_kubernetes_pod_annotation_kubernetes_io_config_hash", "__meta_kubernetes_pod_container_name"] separator = "/" regex = "true/(.*)" target_label = "__path__" replacement = "/var/log/pods/*$1/*.log" } } // Read the kubelet log file of each container on this node. // loki.source.file keeps a read position for each file under // --storage.path, which is the alloy-data hostPath. So when Alloy // restarts, it continues each file at its stored position, and it // does not send the old lines of the file again. // // tail_from_end = false: a file with no stored position starts at // its start. So Alloy sends every line of a new container, also of // a container that stops at once, and every line of a file that // the kubelet makes while Alloy is down. Do not set it to true: // then Alloy does not send the lines that a new file holds before // Alloy opens it. // // At the first start there is no positions file, so Alloy reads // each file from its start one time. The 45m stage.drop in // loki.process "normalise" stops the old lines of that re-read. // // The positions file stores the position of each file under the // path and the target labels of the file. If a change to // discovery.relabel changes the target labels, no file has a // stored position, and Alloy reads every file again from its start. loki.source.file "pods" { targets = discovery.relabel.pod_logs.output forward_to = [loki.process.normalise.receiver] tail_from_end = false // Expand the __path__ glob, and look again for new files every // sync_period (default 10s). file_match { enabled = true } } // Normalise the level field and enforce the approved label set. // See #3347 comment ("label cardinality strategy") for the rules: // * stream/index labels: namespace, app, container, level // * structured metadata: pod, node // * unmatched level -> "unknown" (never drop the line) // // IMPORTANT: loki.process stages read/write the per-entry // `extracted` map, which starts empty for each log line. It is // NOT seeded from the incoming stream labels. So `stage.template` // + `stage.labels` are only appropriate for values genuinely // extracted from the log content here (i.e. `level`). For values // that already arrive as stream labels (namespace, app, container), // defaulting must happen upstream in discovery.relabel — running // template+labels on them would overwrite the good values with // "unknown". `stage.structured_metadata` is different: it falls // back to reading from e.Labels when the extracted key is missing // (see stages/structured_metadata.go), which is why pod/node work. loki.process "normalise" { // Parse the CRI format of the kubelet log file: // "<time> <stream> <flag> <content>". The stage sets the entry // timestamp to <time>, joins partial lines (flag P) into one // line, and keeps only <content> as the line. Keep this stage // first, because the stages below match on the content. stage.cri {} // Drop a line that is more than 45m old when Alloy reads it. This // stage absorbs the one-time re-read at the change to // loki.source.file (#3901). At the first start there is no // positions file, so Alloy reads each log file from its start. // Loki discards a line that is more than 1h behind the newest // line of its stream (max_chunk_age / 2), or older than // reject_old_samples_max_age. Loki stores the other lines of the // push but returns HTTP 400, and loki.write then counts every // entry of the batch as dropped (reason ingester_error). // // 45m is the 1h Loki window minus about 10m, the longest time // that loki.write retries one batch with its default settings. // As a result, a line that passes this stage is still inside the // Loki window when the push arrives. // // Cost: after an Alloy or Loki outage of more than 45m, Alloy // drops the part of the backlog that is older than 45m. // // The contract PR of #3901 removes this stage after the restart // check of #4060 passes: after an Alloy restart that follows the // cutover on all 4 nodes, the new Alloy pods show no // older_than_45m drops. // // Keep this stage directly after stage.cri. Before stage.cri, the // entry timestamp is the time that Alloy read the line, so no // line is old. If this stage moves below the zigbee2mqtt // stage.match, a re-read failure line older than 45m increments // that counter again. stage.drop { older_than = "45m" drop_counter_reason = "older_than_45m" } // Pre-seed extracted[level] = "unknown" for every entry. The // regex/klog stages below will overwrite this if they extract // a level from the log line; if none match, the seed survives // and satisfies the edge-case AC (line with no recognisable // level still ingests with level="unknown"). // // Why a static template value ("unknown") instead of a Go // template that would say "if .Value use it else unknown": // this whole configMap.content string is fed through Helm's // `tpl` function by the alloy chart (templates/configmap.yaml), // which evaluates any Go-template action inside at chart-render // time in Helm's own context (where .Value is nil), collapsing // the Alloy-side Go template into the literal string "unknown" // BEFORE the ConfigMap is even written. Escaping the braces // (backtick-raw-string form, the double-quoted string-brace // idiom, etc.) is either eaten by the outer tpl or unsupported // by its lexer, AND ANY Go-template action sequence inside // this configMap.content string — including ones sitting // harmlessly inside `//` comments — is parsed by tpl, so we // avoid the whole syntax in this file. Pre-seeding sidesteps // the problem: no Go-template syntax inside stage.template, // nothing for Helm to interpret. This latent Helm-tpl // collision was the second half of the #3395 root cause: the // original #3347 pipeline had the same collision for // namespace/app/level, all three rendering as `template = // "unknown"` in the deployed ConfigMap. stage.template { source = "level" template = "unknown" } // Extract a level token from the log line if present. Best-effort; // structured JSON logs, klog-style prefixes (I0101 ...), and plain // words are all common. On no match, stage.regex is a silent // no-op (see stages/regex.go Process) so the "unknown" seed above // survives. stage.regex { expression = "(?i)(?:^|[^A-Za-z])(?P<level>trace|debug|info|warn(?:ing)?|err(?:or)?|fatal|critical|panic)(?:[^A-Za-z]|$)" } // klog-style single-letter prefixes at line start (I0101 ..., W0101 ...). stage.regex { expression = "^(?P<level>[IWED])[0-9]{4}" } // Canonicalise to lowercase {info, warn, error, debug}. Anchored // so partial matches don't collide. // // IMPORTANT: `stage.replace` only substitutes the CAPTURED groups, // not the full match (see stages/replace.go getReplacedEntry). // So the entire input we want to overwrite MUST be wrapped in a // capture group, otherwise the un-captured prefix survives and we // end up with values like "Iinfo", "wwarn", "eerror". This was a // latent bug in the original #3347 pipeline, only unmasked once // #3395 stopped `stage.template` from clobbering level to // "unknown" before anyone could see the real value. stage.replace { source = "level" expression = "^(?i)(i|info)quot; replace = "info" } stage.replace { source = "level" expression = "^(?i)(w|warn(?:ing)?)quot; replace = "warn" } stage.replace { source = "level" expression = "^(?i)(e|err(?:or)?)quot; replace = "error" } stage.replace { source = "level" expression = "^(?i)(d|debug)quot; replace = "debug" } stage.replace { source = "level" expression = "^(?i)(fatal|critical|panic)quot; replace = "error" } stage.replace { source = "level" expression = "^(?i)(trace)quot; replace = "debug" } // Remove the filename label (from loki.source.file) and the stream // label (from stage.cri). stage.metrics below takes its labels // from the entry labels, and filename holds the restart count of // the container. Without this stage, a container restart starts a // new counter series, and increase() does not count the first // sample of a new series (#3920). stage.label_keep removes both // labels from the Loki stream in any case. stage.label_drop { values = ["filename", "stream"] } // zigbee2mqtt failed-command counter (#3885). Only the zigbee2mqtt // stream enters this block, and only failed Publish lines pass the // line filter, so no other entry changes. stage.metrics reads its // labels from the entry label set, so stage.labels promotes device // and reason first. The final stage.label_keep below drops both // from the Loki stream labels. stage.match { selector = "{app=\"zigbee2mqtt\"} |~ \"Publish .* failed\"" stage.regex { expression = "Publish '[^']*' '[^']*' to '(?P<device>[^']*)' failed" } // Seed the reason, then overwrite it for the two known causes. stage.template { source = "reason" template = "other" } stage.regex { expression = "(?P<reason>failed to send ZCL request|No ZCL response received)" } stage.replace { source = "reason" expression = "(failed to send ZCL request)" replace = "send" } stage.replace { source = "reason" expression = "(No ZCL response received)" replace = "timeout" } stage.labels { values = { device = "", reason = "", } } stage.metrics { metric.counter { name = "zigbee2mqtt_command_failures_total" description = "Failed zigbee2mqtt Publish commands, by device and reason." source = "device" action = "inc" // Failures are rare. An expired series restarts at 1, and // Prometheus increase() does not count the first sample of a // new series. A short idle time hides most single failures. max_idle_duration = "8760h" } } } // Promote extracted level -> stream label. namespace/app/container // already arrive as stream labels via discovery.relabel and are // preserved by stage.label_keep below; running them through // stage.labels would be a no-op at best (extracted map is empty // for them) and destructive at worst. stage.labels { values = { level = "", } } // Attach pod + node as structured metadata (Loki 3.x). NOT stream // labels — see the cardinality decision in #3347. stage.structured_metadata { values = { pod = "", node = "", } } // Final gate: drop everything else from the stream index. // Exact list per the Phase 2 spec. stage.label_keep { values = ["app", "container", "level", "namespace"] } forward_to = [loki.write.default.receiver] } // Push to the in-cluster Loki. auth_enabled=false on the Loki side, // so no tenant header / credential is required for intra-cluster // pushes. loki.write "default" { endpoint { url = "http://loki.monitoring.svc:3100/loki/api/v1/push" } }
string
boolean
string
string
string
string
string
string
boolean
alloy.mounts.extra[].mountPath (5)
/var/log/pods
/var/lib/alloy
string
string
boolean
boolean
boolean
alloy.storagePath (4)
/var/lib/alloy
string
string
number
string
number
string
boolean
string
number
boolean
number
boolean
string
boolean
number
number
string
number
number
number
boolean
string
boolean
string
string
string
string
string
rbac.rules[].verbs[] (2)
- get
- list
- watch
string
boolean
string
string
string
string
string
string
string
global.podSecurityContext.fsGroup (1)
${SECURITY_CONTEXT_RUN_AS_GROUP}
string
string
global.podSecurityContext.runAsGroup (1)
${SECURITY_CONTEXT_RUN_AS_GROUP}
string
boolean
global.podSecurityContext.runAsUser (1)
${SECURITY_CONTEXT_RUN_AS_USER}
string
string
string
string
boolean
string