Skip to content

Instantly share code, notes, and snippets.

@carlosroman
Last active June 3, 2025 13:17
Show Gist options
  • Save carlosroman/d0540fe1710132045f09c6e53f086e64 to your computer and use it in GitHub Desktop.
Save carlosroman/d0540fe1710132045f09c6e53f086e64 to your computer and use it in GitHub Desktop.
Datadog operator on Kind cluster

Datadog operator on Kind cluster

Quick and easy install of Datadog Operator on a kind cluster.

Create a .env file with:

DD_API_KEY=<API key>
DD_APP_KEY=<app key>
DD_SITE=<Only if you want to override target site>
"""Simple app to send DogStatsD metrics via UDS streams."""
import logging
import os
import random
import threading
import time
from datadog.dogstatsd import DogStatsd
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(funcName)s - %(message)s')
class DDTester:
"""Class to send DogStatsD metrics via UDS streams."""
def __init__(self, dogstatsd: DogStatsd, tags: list = None):
self.counter = 0
self.dogstatsd = dogstatsd
self.tags = tags
def submit_metrics(self, metric_prefix="test.qa", cardinality=None):
"""Submits all possible metrics types with the given prefix."""
logging.info("Getting ready to submit metrics with prefix '%s' and cardinality '%s'", metric_prefix, cardinality)
counter = 0
while True:
counter += 1
with self.dogstatsd.timed(f"{metric_prefix}.timer", tags=self.tags):
logging.info("Submitting %s metrics", metric_prefix)
self.dogstatsd.gauge(f"{metric_prefix}.gauge", counter, tags=self.tags, cardinality=cardinality)
self.dogstatsd.increment(f"{metric_prefix}.counter_increment", tags=self.tags, cardinality=cardinality)
self.dogstatsd.decrement(f"{metric_prefix}.counter_decrement", tags=self.tags, cardinality=cardinality)
self.dogstatsd.histogram(f"{metric_prefix}.histogram", value=random.gauss(50, 15), tags=self.tags, cardinality=cardinality)
self.dogstatsd.distribution(f"{metric_prefix}.distribution", value=random.gauss(50, 15), tags=self.tags, cardinality=cardinality)
sleep_time = random.expovariate(1/15) # exponential distribution with mean of 15 seconds
sleep_time = min(sleep_time, 60) # cap at 60 seconds
time.sleep(sleep_time)
if __name__ == "__main__":
metric_tags = ["env:dev"]
options = {}
if os.environ.get("UNIXSTREAM_ENABLED", "false").lower() == "true":
options["socket_path"] = "unixstream:///var/run/datadog/statsd-stream.sock"
metric_tags.append("qa_socket:unixstream")
elif os.environ.get("UDS_ENABLED", "false").lower() == "true":
options["socket_path"] = "/var/run/datadog/dsd.socket"
metric_tags.append("qa_socket:uds")
else:
metric_tags.append("qa_socket:udp")
statsd_client = DogStatsd(**options)
tester = DDTester(statsd_client, tags=metric_tags)
metric_cardinality = os.environ.get("METRIC_CARDINALITY", None)
t1 = threading.Thread(target=tester.submit_metrics, kwargs={"cardinality": metric_cardinality})
t1.start()
t1.join()
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dogstatsd-py-app
labels:
environment: qa
app.kubernetes.io/name: datadogpy-test
app.kubernetes.io/instance: xxx
app.kubernetes.io/version: "0.0.0-dev"
app.kubernetes.io/managed-by: skaffold
app.kubernetes.io/component: dogstatsd
app.kubernetes.io/part-of: qa
tags.datadoghq.com/env: qa
tags.datadoghq.com/service: datadogpy-test
tags.datadoghq.com/version: "0.0.0-dev"
spec:
replicas: 2
selector:
matchLabels:
app.kubernetes.io/name: datadogpy-test
template:
metadata:
labels:
app.kubernetes.io/name: datadogpy-test
environment: qa
app.kubernetes.io/instance: xxx
app.kubernetes.io/version: "0.0.0-dev"
app.kubernetes.io/managed-by: skaffold
app.kubernetes.io/component: dogstatsd
app.kubernetes.io/part-of: qa
tags.datadoghq.com/env: qa
tags.datadoghq.com/service: datadogpy-test
tags.datadoghq.com/version: "0.0.0-dev"
spec:
containers:
- name: dogstatsd-py-app
image: skaffold-dogstatsd-unixstream
env:
# - name: UNIXSTREAM_ENABLED
- name: UDS_ENABLED
value: "true"
- name: DD_ENV
value: "qa"
- name: DD_SERVICE
value: "dogstatsd-qa"
- name: METRIC_CARDINALITY
value: "none" # "high" or "low" or "none"
volumeMounts:
- name: datadog-socket
mountPath: /var/run/datadog
readOnly: true
volumes:
- name: datadog-socket
hostPath:
path: /var/run/datadog
type: Directory
---
apiVersion: datadoghq.com/v2alpha1
kind: DatadogAgent
metadata:
name: datadog
spec:
global:
clusterName: my-qa-cluster
site: datadoghq.eu
logLevel: debug
kubelet:
tlsVerify: false
credentials:
apiSecret:
secretName: my-datadog-operator-apikey
keyName: api-key
features:
logCollection:
enabled: true
containerCollectAll: true
dogstatsd:
tagCardinality: high
originDetectionEnabled: true
unixDomainSocketConfig:
enabled: true
apm:
enabled: true
unixDomainSocketConfig:
enabled: true
override:
clusterAgent:
replicas: 1
nodeAgent:
image:
name: "gcr.io/datadoghq/agent:7.67.0-rc.5-full"
env:
- name: DD_HOSTNAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
FROM python:3.11
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
CMD [ "python", "./app.py" ]
---
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: test
nodes:
- role: control-plane
- role: worker
labels:
env: test
kube: kind
- role: worker
labels:
env: qa
kube: kind
- role: worker
labels:
env: prod
kube: kind
include .env
CLI_ARCH := $(shell uname -m)
DD_SITE ?= datadoghq.com
ifeq ($(shell uname -m),aarch64)
CLI_ARCH=arm64
endif
ifeq ($(shell uname -s),Darwin)
CLI_OS=darwin
else
CLI_OS=linux
endif
HELM_CLI ?= $(CURDIR)/bin/helm
KUBECTL_CLI ?= $(CURDIR)/bin/kubectl
KIND_CLI ?= $(CURDIR)/bin/kind
SKAFFOLD_CLI ?= $(CURDIR)/bin/skaffold
PACK_CLI ?= $(CURDIR)/bin/pack
bin/helm : HELM_VERSION = v3.17.0
bin/helm :
@(mkdir -p $(CURDIR)/bin)
@(echo "Downloading https://get.helm.sh/helm-$(HELM_VERSION)-${CLI_OS}-${CLI_ARCH}.tar.gz{,.sha256sum}")
@(curl -L --fail --remote-name-all https://get.helm.sh/helm-$(HELM_VERSION)-${CLI_OS}-${CLI_ARCH}.tar.gz{,.sha256sum})
@(shasum -a 256 -c helm-$(HELM_VERSION)-${CLI_OS}-${CLI_ARCH}.tar.gz.sha256sum)
@tar -xzvf helm-$(HELM_VERSION)-$(CLI_OS)-$(CLI_ARCH).tar.gz --strip-components=1 -C $(CURDIR)/bin/ $(CLI_OS)-$(CLI_ARCH)/helm
@(rm helm-$(HELM_VERSION)-$(CLI_OS)-$(CLI_ARCH).tar.*)
@($(HELM_CLI) version)
bin/kubectl : KUBECTL_VERSION = $(shell curl -L -s https://dl.k8s.io/release/stable.txt)
bin/kubectl :
@(mkdir -p $(CURDIR)/bin)
@(echo "Downloading https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/${CLI_OS}/${CLI_ARCH}/kubectl{,.sha256sum}")
@(curl -L --fail --remote-name-all https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/${CLI_OS}/${CLI_ARCH}/kubectl{,.sha256})
@(sed -i.bak 's/$$/ kubectl/' kubectl.sha256)
@(shasum -a 256 -c kubectl.sha256)
@(rm kubectl.sha256 kubectl.sha256.bak)
@(mv kubectl $(CURDIR)/bin/)
@(chmod +x $(CURDIR)/bin/kubectl)
@($(KUBECTL_CLI) version --client)
bin/kind : KIND_VERSION = v0.29.0
bin/kind :
@(mkdir -p $(CURDIR)/bin)
@(echo "Downloading https://kind.sigs.k8s.io/dl/${KIND_VERSION}/kind-${CLI_OS}-${CLI_ARCH}{,.sha256sum}")
@(curl -L --fail --remote-name-all https://kind.sigs.k8s.io/dl/${KIND_VERSION}/kind-${CLI_OS}-${CLI_ARCH}{,.sha256sum})
@(shasum -a 256 -c kind-${CLI_OS}-${CLI_ARCH}.sha256sum)
@(mv kind-${CLI_OS}-${CLI_ARCH} $(CURDIR)/bin/kind)
@(rm kind-${CLI_OS}-${CLI_ARCH}.sha256sum)
@(chmod +x $(CURDIR)/bin/kind)
@($(KIND_CLI) version)
bin/skaffold : SKAFFOLD_VERSION = v2.16.0
bin/skaffold :
@(mkdir -p $(CURDIR)/bin)
@(echo "Downloading https://github.com/GoogleContainerTools/skaffold/releases/download/${SKAFFOLD_VERSION}/skaffold-${CLI_OS}-${CLI_ARCH}")
@(curl -L --fail --remote-name-all https://github.com/GoogleContainerTools/skaffold/releases/download/${SKAFFOLD_VERSION}/skaffold-${CLI_OS}-${CLI_ARCH}{,.sha256})
@(shasum -a 256 -c skaffold-${CLI_OS}-${CLI_ARCH}.sha256)
@(mv skaffold-${CLI_OS}-${CLI_ARCH} $(CURDIR)/bin/skaffold)
@(rm skaffold-${CLI_OS}-${CLI_ARCH}.sha256)
@(chmod +x $(CURDIR)/bin/skaffold)
@($(SKAFFOLD_CLI) version)
bin/pack : PACK_VERSION = v0.37.0
bin/pack :
@(mkdir -p $(CURDIR)/bin)
@(echo "Downloading https://github.com/buildpacks/pack/releases/download/${PACK_VERSION}/pack-${PACK_VERSION}-${CLI_OS}-${CLI_ARCH}.tgz")
@(curl -L --fail --remote-name-all https://github.com/buildpacks/pack/releases/download/${PACK_VERSION}/pack-${PACK_VERSION}-${CLI_OS}-${CLI_ARCH}.tgz{,.sha256})
@(shasum -a 256 -c pack-${PACK_VERSION}-${CLI_OS}-${CLI_ARCH}.tgz.sha256)
@(tar -xvf pack-${PACK_VERSION}-${CLI_OS}-${CLI_ARCH}.tgz -C $(CURDIR)/bin/)
@(rm pack-${PACK_VERSION}-${CLI_OS}-${CLI_ARCH}.tgz*)
@($(PACK_CLI) version)
.PHONY : install-tools
install-tools : bin/helm
install-tools : bin/kubectl
install-tools : bin/kind
install-tools : bin/skaffold
install-tools : bin/pack
.PHONY : setup
setup : cluster/create
.PHONY : cluster/create
cluster/create :
@($(KIND_CLI) create cluster --config=$(CURDIR)/kind-config.yaml)
@($(KUBECTL_CLI) cluster-info --context kind-test)
@($(KUBECTL_CLI) get svc,pods -A -o wide)
.PHONY : cluster/destroy
cluster/destroy :
@($(KIND_CLI) delete cluster --name=test)
.PHONY : datadog-operator/setup
datadog-operator/setup :
@($(HELM_CLI) repo add datadog https://helm.datadoghq.com)
@($(HELM_CLI) repo update)
@($(HELM_CLI) install my-datadog-operator datadog/datadog-operator \
--namespace datadog --create-namespace \
--set apiKey=$(DD_API_KEY) \
--set appKey=$(DD_APP_KEY) \
--set site=$(DD_SITE))
.PHONY : datadog-operator/agent
datadog-operator/agent :
@($(KUBECTL_CLI) apply \
-f $(CURDIR)/datadog-agent.yaml \
--namespace=datadog)
.PHONY : debug
debug :
@echo "KIND_CLI: $(KIND_CLI)"
@echo "KUBECTL_CLI: $(KUBECTL_CLI)"
@echo "HELM_CLI: $(HELM_CLI)"
@echo "CLI_OS: $(CLI_OS)"
@echo "CLI_ARCH: $(CLI_ARCH)"
@echo "DD_API_KEY: $(DD_API_KEY)"
@echo "DD_APP_KEY: $(DD_APP_KEY)"
@echo "DD_SITE: $(DD_SITE)"
.PHONY : k/pods
k/pods :
@($(KUBECTL_CLI) get pods -A -o wide ${args})
# datadog @ git+https://github.com/DataDog/datadogpy.git@8b86b83238f02d348f70845c4c769becb60b64f4
datadog @ git+https://github.com/DataDog/datadogpy.git@8c2f1fce980daead5afc0376bfa8bced2071abc5
---
apiVersion: skaffold/v4beta13
kind: Config
metadata:
name: dogstatsd-py-app
build:
artifacts:
- image: skaffold-dogstatsd-py-app
docker:
dockerfile: Dockerfile
manifests:
rawYaml:
- app.yaml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment