The additionalManifests value lets you deploy arbitrary Kubernetes objects alongside the ClickStack chart. Use it for resources that the chart does not template natively, such as NetworkPolicy, HorizontalPodAutoscaler, ServiceAccount, PodMonitor, custom Ingress objects, or any other Kubernetes API object.
Each entry in additionalManifests is a complete Kubernetes resource definition. The chart:
- Iterates over each entry in the list
- Converts the entry to YAML (
toYaml) - Evaluates template expressions in that YAML using Helm
tpl
Template expressions can reference:
.Release.Name,.Release.Namespaceinclude "clickstack.fullname" .and other chart helpers.Values.*
additionalManifests:
- apiVersion: v1
kind: ConfigMap
metadata:
name: '{{ include "clickstack.fullname" . }}-custom'
data:
release: '{{ .Release.Name }}'additionalManifests is configured in a values file, and values files are parsed as YAML before tpl runs.
- Any
{{ ... }}in a values file must be inside a quoted string. - Structural template blocks are not valid values YAML (for example,
{{- include ... | nindent ... }}by itself). - For non-string fields (for example, numeric ports), use literal values or named ports.
- If you need structural templating, use a wrapper chart template instead of a raw values file.
# Valid in values.yaml
name: '{{ include "clickstack.fullname" . }}-app'
# Invalid in values.yaml (unquoted template expression)
name: {{ include "clickstack.fullname" . }}-app
# Invalid in values.yaml (structural template block)
labels:
{{- include "clickstack.labels" . | nindent 2 }}These helpers are defined in templates/_helpers.tpl:
| Helper | Description | Values-file usage |
|---|---|---|
clickstack.name |
Chart name (truncated to 63 chars) | Safe in quoted scalars |
clickstack.fullname |
Release-qualified name | Safe in quoted scalars |
clickstack.chart |
Chart name + version | Safe in quoted scalars |
clickstack.selectorLabels |
Selector labels block | Wrapper chart templates only |
clickstack.labels |
Standard labels block | Wrapper chart templates only |
clickstack.mongodb.fullname |
MongoDB CR name | Safe in quoted scalars |
clickstack.clickhouse.fullname |
ClickHouse CR name | Safe in quoted scalars |
clickstack.otel.fullname |
OTEL Collector name | Safe in quoted scalars |
additionalManifests:
- apiVersion: v1
kind: ServiceAccount
metadata:
name: '{{ include "clickstack.fullname" . }}'
namespace: '{{ .Release.Namespace }}'
labels:
app.kubernetes.io/name: '{{ include "clickstack.name" . }}'
app.kubernetes.io/instance: '{{ .Release.Name }}'
annotations:
eks.amazonaws.com/role-arn: "arn:aws:iam::123456789:role/my-role"Restrict ingress traffic to HyperDX pods:
additionalManifests:
- apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: '{{ include "clickstack.fullname" . }}-allow-ingress'
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: '{{ include "clickstack.name" . }}'
app.kubernetes.io/instance: '{{ .Release.Name }}'
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- protocol: TCP
port: 3000
- protocol: TCP
port: 8000additionalManifests:
- apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: '{{ include "clickstack.fullname" . }}-hpa'
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: '{{ include "clickstack.fullname" . }}-app'
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75additionalManifests:
- apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: '{{ include "clickstack.fullname" . }}'
labels:
release: prometheus
spec:
selector:
matchLabels:
app.kubernetes.io/name: '{{ include "clickstack.name" . }}'
app.kubernetes.io/instance: '{{ .Release.Name }}'
podMetricsEndpoints:
- port: app
interval: 30sWhen using the AWS Load Balancer Controller, disable the chart's built-in nginx Ingress and define a custom ALB Ingress:
hyperdx:
ingress:
enabled: false
additionalManifests:
- apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: '{{ include "clickstack.fullname" . }}-alb'
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:us-east-1:123456789:certificate/abc-123"
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
alb.ingress.kubernetes.io/ssl-redirect: "443"
alb.ingress.kubernetes.io/group.name: clickstack
alb.ingress.kubernetes.io/healthcheck-path: /api/health
spec:
ingressClassName: alb
rules:
- host: clickstack.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: '{{ include "clickstack.fullname" . }}-app'
port:
name: appFor a complete ALB setup example, see examples/alb-ingress/.
For ALB scenarios that require explicit TargetGroupBinding resources:
additionalManifests:
- apiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
name: '{{ include "clickstack.fullname" . }}-tgb'
spec:
serviceRef:
name: '{{ include "clickstack.fullname" . }}-app'
port: app
targetGroupARN: "arn:aws:elasticloadbalancing:us-east-1:123456789:targetgroup/my-tg/abc123"
targetType: ipIf you need structural helpers like include "clickstack.labels" . | nindent 4, render them from a wrapper chart template (templates/*.yaml) instead of putting those blocks directly in values files.
Example wrapper chart template snippet:
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "clickstack.fullname" . }}-extra
labels:
{{- include "clickstack.labels" . | nindent 4 }}
data:
appPort: "{{ .Values.hyperdx.ports.app }}"Each additionalManifests entry is rendered as a separate YAML document. You can add Helm hook annotations to control install/upgrade ordering:
additionalManifests:
- apiVersion: batch/v1
kind: Job
metadata:
name: post-install-job
annotations:
helm.sh/hook: post-install
helm.sh/hook-delete-policy: hook-succeeded
spec:
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: my-migration-image:latest
command: ["./migrate.sh"]If your additional manifests include custom resources (for example, PodMonitor), the CRDs must already exist in the cluster before install/upgrade.
additionalManifests is a list. Entries are rendered in list order, and each entry becomes its own YAML document.