Skip to content
Draft
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
31 changes: 25 additions & 6 deletions app/functions/helmless/default-values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,9 @@ components:
# per node. This is equivalent to setting defaults.federation.enabled to true.
# Uses Prometheus in server mode for metrics collection.
#
# - "clustered": EXPERIMENTAL. Uses Grafana Alloy instead of Prometheus for
# metrics collection. Alloy provides better performance and native
# horizontal scalability.
# - "clustered": EXPERIMENTAL. Uses the embedded CloudZero Alloy binary for
# metrics collection instead of Prometheus. Alloy provides better
# performance and native horizontal scalability.
#
# - null means automatic mode (currently defaults to "agent").
mode: null
Expand Down Expand Up @@ -406,10 +406,29 @@ components:
# The agent clustered node component configuration.
# Only applies when components.agent.mode is set to "clustered".
clusteredNode:
# Container image configuration for Grafana Alloy.
# Container image override for the Alloy container.
#
# By default, the CloudZero Alloy binary is embedded in the agent
# image and the Alloy container uses the same image as other agent
# containers (components.agent.image). Set repository/tag here only
# if you need to override the Alloy container image separately.
image:
repository: docker.io/grafana/alloy
tag: v1.11.3
repository: null
tag: null
# Command to run in the Alloy container.
#
# - null (default): Uses /app/cloudzero-alloy (CloudZero Alloy binary)
# - []: Uses the image's default entrypoint (for official Alloy image)
# - ["/custom/path"]: Uses the specified command
#
# To use the official Grafana Alloy image instead of the embedded binary:
#
# image:
# repository: docker.io/grafana/alloy
# tag: vX.Y.Z
# command: []
#
command:

# Resource requirements and limits for the container.
#
Expand Down
11 changes: 9 additions & 2 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ ARG DEPLOY_IMAGE=scratch
# 2. dependencies: Download Go modules (cached per platform)
# 3. builder: Build Go binaries (cached per platform)
# 4. certs: Extract certificates from distroless image
# 5. final: Minimal runtime image with compiled binaries
# 5. alloy: Extract Alloy binary from CloudZero Alloy image
# 6. final: Minimal runtime image with compiled binaries

# Stage 1: Base tools installation
FROM --platform=$BUILDPLATFORM golang:1.25.6-alpine AS base-tools
Expand Down Expand Up @@ -69,7 +70,10 @@ RUN --mount=type=cache,target=/go/pkg/mod,id=gomod-$TARGETPLATFORM \
# Stage 4: Access current certs
FROM gcr.io/distroless/static-debian12:debug@sha256:20d9c135406d8029d30d59eaaa9d62d2edcd4ec5915dbcda324243c40460e8df AS certs

# Stage 5: Final runtime image
# Stage 5: Extract Alloy binary from CloudZero Alloy image
FROM ghcr.io/evan-cz/alloy:latest AS alloy

# Stage 6: Final runtime image
# Note: For debugging, you can temporarily change the image used for building by
# passing in something like this to 'docker build':
#
Expand Down Expand Up @@ -113,6 +117,9 @@ COPY --from=builder /go/bin/cloudzero-helmless /app/cloudzero-helmless
COPY --from=builder /go/bin/cloudzero-scout /app/cloudzero-scout
COPY --from=builder /go/bin/cloudzero-certifik8s /app/cloudzero-certifik8s

# Copy the Alloy binary from the alloy stage
COPY --from=alloy /bin/cloudzero-alloy /app/cloudzero-alloy

# Allow the default ENTRYPOINT from busybox to be the default,
# however run the app as the default command
CMD ["/app/cloudzero-agent-validator", "-h"]
20 changes: 20 additions & 0 deletions helm/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,26 @@ configuration will not overwrite values from the first configuration.
{{- end -}}
{{- end -}}

{{/*
Generate container command with special handling:
- null/not set: Uses provided default command array
- empty array []: No command output (uses image's default entrypoint)
- non-empty array: Uses the specified command

Usage: {{ include "cloudzero-agent.generateContainerCommand" (dict "command" .Values.components.agent.clusteredNode.command "default" (list "/app/cloudzero-alloy")) | nindent 10 }}
*/}}
{{- define "cloudzero-agent.generateContainerCommand" -}}
{{- $isEmptyArray := and (kindIs "slice" .command) (empty .command) -}}
{{- if not $isEmptyArray -}}
command:
{{- if kindIs "invalid" .command }}
{{- toYaml .default | nindent 2 }}
{{- else }}
{{- toYaml .command | nindent 2 }}
{{- end }}
{{- end -}}
{{- end -}}

{{/*
Generate image configuration with defaults.
*/}}
Expand Down
6 changes: 3 additions & 3 deletions helm/templates/agent-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,10 @@ spec:
{{- include "cloudzero-agent.apiKeyVolumeMount" . | nindent 12 }}
{{- end }}{{/* End Prometheus container */}}
{{- if eq (include "cloudzero-agent.Values.components.agent.mode" .) "clustered" }}
# Grafana Alloy container
# CloudZero Alloy container (binary embedded in agent image)
- name: {{ template "cloudzero-agent.name" . }}-alloy
{{- $alloyImage := include "cloudzero-agent.agentCollectorImage" . | fromYaml }}
{{- include "cloudzero-agent.generateImage" (dict "defaults" .Values.defaults.image "image" $alloyImage) | nindent 10 }}
{{- include "cloudzero-agent.generateImage" (dict "defaults" .Values.defaults.image "image" .Values.components.agent.image "compat" .Values.components.agent.clusteredNode.image) | nindent 10 }}
{{- include "cloudzero-agent.generateContainerCommand" (dict "command" .Values.components.agent.clusteredNode.command "default" (list "/app/cloudzero-alloy")) | nindent 10 }}
args:
- run
- /etc/alloy/alloy-config.river
Expand Down
6 changes: 5 additions & 1 deletion helm/tests/alloy_deployment_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ tests:
template: templates/agent-deploy.yaml
- matchRegex:
path: spec.template.spec.containers[1].image
pattern: grafana/alloy
pattern: cloudzero-agent
template: templates/agent-deploy.yaml
- isNull:
path: data["prometheus.yml"]
Expand Down Expand Up @@ -84,6 +84,10 @@ tests:
set:
components.agent.mode: clustered
asserts:
- contains:
path: spec.template.spec.containers[1].command
content: /app/cloudzero-alloy
template: templates/agent-deploy.yaml
- contains:
path: spec.template.spec.containers[1].args
content: run
Expand Down
27 changes: 12 additions & 15 deletions helm/tests/alloy_image_configuration_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,33 @@ suite: test Alloy image configuration
templates:
- templates/agent-deploy.yaml
tests:
# Test default Alloy image
- it: should use default Alloy image from components.agent.clusteredNode.image
# Test that Alloy container uses the agent image (Alloy binary is embedded)
- it: should use the agent image for the Alloy container
set:
components.agent.mode: clustered
asserts:
- matchRegex:
path: spec.template.spec.containers[1].image
pattern: docker.io/grafana/alloy:v1.11.3
pattern: cloudzero-agent

# Test custom Alloy image
- it: should use custom Alloy image when specified
# Test custom agent image applies to Alloy container
- it: should use custom agent image when specified
set:
components.agent.mode: clustered
components.agent.clusteredNode.image:
repository: custom.registry.io/custom/alloy
components.agent.image:
repository: custom.registry.io/custom/agent
tag: v2.0.0
asserts:
- matchRegex:
path: spec.template.spec.containers[1].image
pattern: custom.registry.io/custom/alloy:v2.0.0
pattern: custom.registry.io/custom/agent:v2.0.0

# Test that alloy image is only used for Alloy
# Test that Alloy image config does not affect Prometheus image
- it: should not affect Prometheus image
set:
components.agent.mode: agent
components.agent.autoscaling:
enabled: false
components.agent.clusteredNode.image:
repository: custom.registry.io/custom/alloy
tag: v2.0.0
asserts:
- matchRegex:
path: spec.template.spec.containers[1].image
Expand All @@ -40,11 +37,11 @@ tests:
path: spec.template.spec.containers[1].image
pattern: alloy

# Test image pull policy from components.agent.clusteredNode.image
- it: should respect pullPolicy from components.agent.clusteredNode.image
# Test image pull policy from components.agent.image
- it: should respect pullPolicy from components.agent.image
set:
components.agent.mode: clustered
components.agent.clusteredNode.image:
components.agent.image:
pullPolicy: Always
asserts:
- equal:
Expand Down
10 changes: 10 additions & 0 deletions helm/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -5856,6 +5856,16 @@
"clusteredNode": {
"additionalProperties": false,
"properties": {
"command": {
"oneOf": [
{
"$ref": "#/$defs/io.k8s.api.core.v1.Container/properties/command"
},
{
"type": "null"
}
]
},
"image": {
"$ref": "#/$defs/com.cloudzero.agent.image"
},
Expand Down
13 changes: 12 additions & 1 deletion helm/values.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -666,8 +666,19 @@ properties:
properties:
image:
description: |
Container image configuration for Grafana Alloy.
Container image override for the Alloy container. By default, the Alloy
container uses the agent image (components.agent.image) which embeds the
CloudZero Alloy binary. Set repository/tag here to override separately.
$ref: "#/$defs/com.cloudzero.agent.image"
command:
description: |
Command to run in the Alloy container.
- null (default): Uses /app/cloudzero-alloy (CloudZero Alloy binary)
- [] (empty array): Uses the image's default entrypoint
- ["/custom/path"]: Uses the specified command
oneOf:
- $ref: "#/$defs/io.k8s.api.core.v1.Container/properties/command"
- type: "null"
resources:
description: |
Resource requirements and limits for the Alloy container.
Expand Down
31 changes: 25 additions & 6 deletions helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,9 @@ components:
# per node. This is equivalent to setting defaults.federation.enabled to true.
# Uses Prometheus in server mode for metrics collection.
#
# - "clustered": EXPERIMENTAL. Uses Grafana Alloy instead of Prometheus for
# metrics collection. Alloy provides better performance and native
# horizontal scalability.
# - "clustered": EXPERIMENTAL. Uses the embedded CloudZero Alloy binary for
# metrics collection instead of Prometheus. Alloy provides better
# performance and native horizontal scalability.
#
# - null means automatic mode (currently defaults to "agent").
mode: null
Expand Down Expand Up @@ -406,10 +406,29 @@ components:
# The agent clustered node component configuration.
# Only applies when components.agent.mode is set to "clustered".
clusteredNode:
# Container image configuration for Grafana Alloy.
# Container image override for the Alloy container.
#
# By default, the CloudZero Alloy binary is embedded in the agent
# image and the Alloy container uses the same image as other agent
# containers (components.agent.image). Set repository/tag here only
# if you need to override the Alloy container image separately.
image:
repository: docker.io/grafana/alloy
tag: v1.11.3
repository: null
tag: null
# Command to run in the Alloy container.
#
# - null (default): Uses /app/cloudzero-alloy (CloudZero Alloy binary)
# - []: Uses the image's default entrypoint (for official Alloy image)
# - ["/custom/path"]: Uses the specified command
#
# To use the official Grafana Alloy image instead of the embedded binary:
#
# image:
# repository: docker.io/grafana/alloy
# tag: vX.Y.Z
# command: []
#
command:

# Resource requirements and limits for the container.
#
Expand Down
11 changes: 7 additions & 4 deletions tests/helm/template/alloy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -966,9 +966,10 @@ data:
annotations: {}
autoscaling: null
clusteredNode:
command: null
image:
repository: docker.io/grafana/alloy
tag: v1.11.3
repository: null
tag: null
resources:
limits:
cpu: 100m
Expand Down Expand Up @@ -2601,10 +2602,12 @@ spec:
- name: config-volume
mountPath: /etc/config
readOnly: true
# Grafana Alloy container
# CloudZero Alloy container (binary embedded in agent image)
- name: cloudzero-agent-alloy
image: "docker.io/grafana/alloy:v1.11.3"
image: "ghcr.io/cloudzero/cloudzero-agent/cloudzero-agent:1.2.9"
imagePullPolicy: "IfNotPresent"
command:
- /app/cloudzero-alloy
args:
- run
- /etc/alloy/alloy-config.river
Expand Down
5 changes: 3 additions & 2 deletions tests/helm/template/cert-manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -883,9 +883,10 @@ data:
annotations: {}
autoscaling: null
clusteredNode:
command: null
image:
repository: docker.io/grafana/alloy
tag: v1.11.3
repository: null
tag: null
resources:
limits:
cpu: 100m
Expand Down
5 changes: 3 additions & 2 deletions tests/helm/template/federated.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -971,9 +971,10 @@ data:
annotations: {}
autoscaling: null
clusteredNode:
command: null
image:
repository: docker.io/grafana/alloy
tag: v1.11.3
repository: null
tag: null
resources:
limits:
cpu: 100m
Expand Down
5 changes: 3 additions & 2 deletions tests/helm/template/istio.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -898,9 +898,10 @@ data:
annotations: {}
autoscaling: null
clusteredNode:
command: null
image:
repository: docker.io/grafana/alloy
tag: v1.11.3
repository: null
tag: null
resources:
limits:
cpu: 100m
Expand Down
5 changes: 3 additions & 2 deletions tests/helm/template/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -898,9 +898,10 @@ data:
annotations: {}
autoscaling: null
clusteredNode:
command: null
image:
repository: docker.io/grafana/alloy
tag: v1.11.3
repository: null
tag: null
resources:
limits:
cpu: 100m
Expand Down
Loading