Skip to main content

Kubernetes Deployment

infrasagent runs as a DaemonSet (one pod per node) for host-level telemetry collection, or as a Deployment in gateway mode for centralized aggregation.


DaemonSet (Agent Mode)

The DaemonSet deploys one agent per node to collect host metrics, container logs, and OTLP from local workloads.

1. Create the namespace and secret

kubectl create namespace infrasage

kubectl create secret generic infrasagent \
--namespace infrasage \
--from-literal=api-key=<YOUR_API_KEY>

2. Apply the ConfigMap

# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: infrasagent
namespace: infrasage
data:
agent.yaml: |
agent:
name: "${HOSTNAME}-agent"
mode: agent

api:
listen: "0.0.0.0:8080"

sources:
otlp_in:
type: otlp
grpc:
listen: "0.0.0.0:4317"
http:
listen: "0.0.0.0:4318"

host_metrics:
type: hostmetrics
collection_interval: 15s
scrapers: [cpu, memory, disk, network, load, processes]

docker_logs:
type: docker_logs

k8s_events:
type: k8s_events

processors:
k8s_enrich:
type: k8s_attributes
sources: [otlp_in, docker_logs, k8s_events]

batch_main:
type: batch
timeout: 5s
max_size: 10000
sources: [k8s_enrich, host_metrics]

sinks:
infrasage:
type: otlp
endpoint: "https://api.infrasage.dev"
protocol: http
auth_header: "Bearer ${INFRASAGE_API_KEY}"
sources: [batch_main]
kubectl apply -f configmap.yaml

3. Apply the DaemonSet and RBAC

# daemonset.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: infrasagent
namespace: infrasage
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: infrasagent
rules:
- apiGroups: [""]
resources: [pods, namespaces, nodes, events]
verbs: [get, list, watch]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: infrasagent
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: infrasagent
subjects:
- kind: ServiceAccount
name: infrasagent
namespace: infrasage
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: infrasagent
namespace: infrasage
spec:
selector:
matchLabels:
app: infrasagent
template:
metadata:
labels:
app: infrasagent
spec:
serviceAccountName: infrasagent
tolerations:
- effect: NoSchedule
operator: Exists
containers:
- name: agent
image: ghcr.io/infrasage/infrasagent:latest
args: ["-config", "/etc/infrasagent/agent.yaml"]
env:
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: INFRASAGE_API_KEY
valueFrom:
secretKeyRef:
name: infrasagent
key: api-key
ports:
- name: otlp-grpc
containerPort: 4317
- name: otlp-http
containerPort: 4318
- name: admin
containerPort: 8080
volumeMounts:
- name: config
mountPath: /etc/infrasagent
- name: docker-sock
mountPath: /var/run/docker.sock
readOnly: true
- name: host-proc
mountPath: /host/proc
readOnly: true
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
volumes:
- name: config
configMap:
name: infrasagent
- name: docker-sock
hostPath:
path: /var/run/docker.sock
- name: host-proc
hostPath:
path: /proc
kubectl apply -f daemonset.yaml

4. Verify

kubectl -n infrasage get pods
# NAME READY STATUS RESTARTS AGE
# infrasagent-x4k2p 1/1 Running 0 30s
# infrasagent-7j9qm 1/1 Running 0 30s

kubectl -n infrasage logs daemonset/infrasagent | tail -5

Helm Chart

helm repo add infrasage https://charts.infrasage.io
helm repo update

helm install infrasagent infrasage/infrasagent \
--namespace infrasage \
--create-namespace \
--set config.sinks.infrasage.authHeader="Bearer ${INFRASAGE_API_KEY}"

Key values:

# values.yaml
image:
repository: ghcr.io/infrasage/infrasagent
tag: latest

daemonset:
enabled: true
tolerations:
- effect: NoSchedule
operator: Exists

resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi

config:
sources:
hostmetrics:
enabled: true
collection_interval: 15s
docker_logs:
enabled: true
k8s_events:
enabled: true
sinks:
infrasage:
endpoint: "https://api.infrasage.dev"
protocol: http
authHeader: "" # set via --set or existingSecret

Sending OTLP from Pods

Configure your applications to send OTLP to the agent running on the same node using the downward API:

# In your application pod
env:
- name: NODE_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://$(NODE_IP):4318"
- name: OTEL_SERVICE_NAME
value: "my-service"