Kubernetes Deployment
Deploy Radar Collector in Kubernetes using Deployments, ConfigMaps, and Secrets for scalable monitoring.
Prerequisites
- Kubernetes cluster (1.19+)
kubectlconfigured to access your cluster- Container image of Radar Collector
Container Image
The Radar Collector is published to GHCR:
# Pull the latest stable alpine image (recommended)
docker pull ghcr.io/redis-field-engineering/radar-collector:alpine-latest
# Or pin to a specific version (recommended for production)
docker pull ghcr.io/redis-field-engineering/radar-collector:alpine-v1.2.1
The default entrypoint and command in the published image are:
ENTRYPOINT ["/usr/local/bin/radar-collector"]
CMD ["--config", "/etc/radar/radar-collector.yml"]
Quick Start
1. Create Namespace
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: radar-collector
labels:
name: radar-collector
kubectl apply -f namespace.yaml
2. Create Secrets
Store sensitive configuration in Kubernetes Secrets.
Obtaining an API key: Log in to the Radar dashboard and navigate to Settings > Access Keys to generate a new key.
# secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: radar-collector-secrets
namespace: radar-collector
type: Opaque
stringData:
api-key: "your-radar-api-key"
enterprise-basic-auth: "admin@cluster.local:enterprise-password"
For Redis Software, enterprise-basic-auth must be a single username:password value because the collector uses it for REST API basic auth. For direct Redis connections such as standalone or cluster, store only the Redis password in the Secret, for example redis-password: "your-redis-password", and reference that from ${REDIS_STANDALONE_PASSWORD} or ${REDIS_CLUSTER_PASSWORD}. If you use Redis ACLs, keep the username as a separate field in the collector config.
Create radar-collector-secrets in the same namespace as the collector Deployment. This repository does not include a committed staging copy of that Secret, so if your collector runs in staging, create the Secret in staging and update the manifest namespace accordingly.
kubectl apply -f secrets.yaml
3. Create ConfigMap
Store the collector configuration:
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: radar-collector-config
namespace: radar-collector
data:
radar-collector.yml: |
collector:
id: "radar-collector-k8s-${HOSTNAME}"
hostname: "${HOSTNAME}"
collection_interval: "30s"
remote_config:
enabled: false
server:
grpc_url: "https://grpc.radar.redis.io:443"
api_key: "${RADAR_API_KEY}"
deployments:
- id: "redis-enterprise"
name: "Redis Software Production"
type: "enterprise"
rest_api:
host: "cluster.redis.local"
port: 9443
use_tls: true
insecure: true
enterprise_admin_url: "https://cluster.redis.local:8443"
enterprise:
db_endpoint: external_ip
credentials:
rest_api:
basic_auth: "${ENTERPRISE_BASIC_AUTH}"
kubectl apply -f configmap.yaml
4. Create Deployment
Deploy the Radar Collector:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: radar-collector
namespace: radar-collector
labels:
app: radar-collector
spec:
replicas: 1
selector:
matchLabels:
app: radar-collector
template:
metadata:
labels:
app: radar-collector
spec:
serviceAccountName: radar-collector
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: radar-collector
image: ghcr.io/redis-field-engineering/radar-collector:alpine-latest
imagePullPolicy: Always
env:
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: RADAR_API_KEY
valueFrom:
secretKeyRef:
name: radar-collector-secrets
key: api-key
- name: ENTERPRISE_BASIC_AUTH
valueFrom:
secretKeyRef:
name: radar-collector-secrets
key: enterprise-basic-auth
- name: RUST_LOG
value: "info"
volumeMounts:
- name: config
mountPath: /etc/radar
readOnly: true
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "200m"
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumes:
- name: config
configMap:
name: radar-collector-config
restartPolicy: Always
nodeSelector:
kubernetes.io/os: linux
5. Create ServiceAccount and RBAC
Create service account with minimal permissions:
# rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: radar-collector
namespace: radar-collector
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: radar-collector
namespace: radar-collector
rules:
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: radar-collector
namespace: radar-collector
subjects:
- kind: ServiceAccount
name: radar-collector
namespace: radar-collector
roleRef:
kind: Role
name: radar-collector
apiGroup: rbac.authorization.k8s.io
kubectl apply -f rbac.yaml
kubectl apply -f deployment.yaml
Deployment Type Reference
The examples above use Redis Software by default. If you are collecting from a different deployment type, replace the deployments entry in radar-collector.yml and update the referenced secret/env var names to match.
Redis Software (type: enterprise)
The collector connects to the Redis Software REST API to discover all databases in the cluster. It does not connect directly to individual Redis instances for collection.
- id: "redis-enterprise"
name: "Redis Software Production"
type: "enterprise"
rest_api:
host: "cluster.redis.local" # REST API hostname
port: 9443 # REST API port (typically 9443)
use_tls: true # Use HTTPS (recommended for production)
insecure: true # Skip cert verification (for self-signed certs)
enterprise_admin_url: "https://cluster.redis.local:8443" # Optional management UI link
enterprise:
db_endpoint: external_ip # How to report DB endpoints: external_ip, internal_ip, or dns
credentials:
rest_api:
basic_auth: "${ENTERPRISE_BASIC_AUTH}" # "username:password" format
Network requirements: The collector pod needs egress to the REST API host on port 9443 (HTTPS).
Secret value: enterprise-basic-auth: "username:password"
Standalone (type: standalone)
Connects directly to a single Redis instance. Use rediss:// for TLS.
- id: "redis-cache"
name: "Session Cache"
type: "standalone"
redis_url: "redis://redis-cache.svc.cluster.local:6379"
credentials:
password: "${REDIS_STANDALONE_PASSWORD}"
Network requirements: Egress to the Redis host on port 6379 (or 6380 for TLS).
Secret value: redis-password: "your-redis-password"
Cluster (type: cluster)
Provide seed nodes. The collector runs CLUSTER NODES to automatically discover the full topology, then collects from every node.
- id: "redis-cluster"
name: "Data Cluster"
type: "cluster"
redis_urls:
- "redis-node-0.svc.cluster.local:7000"
- "redis-node-1.svc.cluster.local:7000"
- "redis-node-2.svc.cluster.local:7000"
credentials:
username: "radar-agent" # Optional ACL username
password: "${REDIS_CLUSTER_PASSWORD}"
Network requirements: Egress to every cluster node on the Redis port. Since the collector discovers nodes dynamically, ensure network policies allow traffic to all nodes in the cluster, not just the seed nodes.
Secret value: redis-cluster-password: "your-redis-password" with optional username in the collector config when ACLs are enabled.
Advanced Configuration
Multi-Environment Setup
Deploy different collectors for different environments:
# production-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: radar-collector-production
namespace: radar-collector
spec:
replicas: 1
selector:
matchLabels:
app: radar-collector
environment: production
template:
metadata:
labels:
app: radar-collector
environment: production
spec:
containers:
- name: radar-collector
image: ghcr.io/redis-field-engineering/radar-collector:alpine-latest
env:
- name: ENVIRONMENT
value: "production"
volumeMounts:
- name: config
mountPath: /etc/radar
volumes:
- name: config
configMap:
name: radar-collector-config-production
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: radar-collector-staging
namespace: radar-collector
spec:
replicas: 1
selector:
matchLabels:
app: radar-collector
environment: staging
template:
metadata:
labels:
app: radar-collector
environment: staging
spec:
containers:
- name: radar-collector
image: ghcr.io/redis-field-engineering/radar-collector:alpine-latest
env:
- name: ENVIRONMENT
value: "staging"
volumeMounts:
- name: config
mountPath: /etc/radar
volumes:
- name: config
configMap:
name: radar-collector-config-staging
Network Policies
Restrict network access:
# network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: radar-collector-netpol
namespace: radar-collector
spec:
podSelector:
matchLabels:
app: radar-collector
policyTypes:
- Egress
egress:
# Allow DNS resolution
- to: []
ports:
- protocol: UDP
port: 53
# Allow HTTPS/gRPC to Radar server
- to: []
ports:
- protocol: TCP
port: 443
# Allow Redis Software REST API
- to: []
ports:
- protocol: TCP
port: 9443
If you switch the collector to type: standalone, allow egress to the Redis host on 6379 or 6380. If you switch to type: cluster, allow egress to the seed nodes and all discovered cluster nodes, commonly on port 7000.
TLS and Corporate CA Certificates
If your environment uses a corporate proxy or private CA, the collector’s TLS library cannot verify the Radar gRPC server certificate by default. Mount a complete CA bundle into the container to resolve this.
Mount CA Bundle
Add the CA bundle as a ConfigMap or Secret and mount it into the container:
apiVersion: v1
kind: ConfigMap
metadata:
name: corporate-ca
namespace: radar-collector
data:
ca-bundle.crt: |
-----BEGIN CERTIFICATE-----
... system and corporate CA certificates ...
-----END CERTIFICATE-----
Then add the volume and mount to your Deployment:
spec:
containers:
- name: radar-collector
image: ghcr.io/redis-field-engineering/radar-collector:alpine-latest
volumeMounts:
- name: config
mountPath: /etc/radar
readOnly: true
- name: ca-cert
mountPath: /etc/radar/certs/ca-bundle.crt
subPath: ca-bundle.crt
readOnly: true
volumes:
- name: config
configMap:
name: radar-collector-config
- name: ca-cert
configMap:
name: corporate-ca
Important: Do not mount a single corporate CA certificate over
/etc/ssl/certs/ca-certificates.crtunless that file is a complete CA bundle. Replacing the system bundle with a single certificate can break TLS verification for endpoints that rely on public CAs.
Using SSL_CERT_FILE
Set SSL_CERT_FILE only when it points to a complete CA bundle:
env:
- name: SSL_CERT_FILE
value: "/etc/radar/certs/ca-bundle.crt"
Management and Operations
View Logs
kubectl logs -n radar-collector -l app=radar-collector -f
kubectl logs -n radar-collector <pod-name> -f
kubectl logs -n radar-collector <pod-name> --previous
Update Configuration
kubectl apply -f configmap.yaml
kubectl rollout restart deployment/radar-collector -n radar-collector
kubectl rollout status deployment/radar-collector -n radar-collector
Troubleshooting
Common Issues
Pod won’t start:
kubectl get pods -n radar-collector
kubectl describe pod <pod-name> -n radar-collector
kubectl logs <pod-name> -n radar-collector
Configuration issues:
kubectl get configmap radar-collector-config -n radar-collector -o yaml
kubectl exec -it <pod-name> -n radar-collector -- radar-collector --validate --config /etc/radar/radar-collector.yml
Health Checks
kubectl get deployment radar-collector -n radar-collector
kubectl get pods -n radar-collector -l app=radar-collector
kubectl get events -n radar-collector --sort-by='.lastTimestamp'