Kubernetes

Datadog Agent로 Traefik pod의 로그를 Datadog으로 전송하기

mokpolar 2025. 2. 26. 17:40
반응형

안녕하세요?
AEWS 스터디 4주차 EKS Observability 과제 시작하겠습니다.

 

이번 주제는 Datadog Agent로 Traefik pod의 로그를 Datadog으로 전송하기 입니다.

테스트를 완료하면 아래와 같은 모습이 됩니다.

Kind를 이용한 K8S 클러스터 환경 준비

관련 필수 툴을 설치하겠습니다.

# Install Kind
brew install kind
kind --version

# Install kubectl
brew install kubernetes-cli
kubectl version --client=true

## kubectl -> k 단축키 설정
echo "alias kubectl=kubecolor" >> ~/.zshrc

# Install Helm
brew install helm
helm version

필요한 툴들도 설치해줍니다.

# 툴 설치
brew install krew
brew install kube-ps1
brew install kubectx

# kubectl 출력 시 하이라이트 처리
brew install kubecolor
echo "alias kubectl=kubecolor" >> ~/.zshrc
echo "compdef kubecolor=kubectl" >> ~/.zshrc

# krew 플러그인 설치
kubectl krew install neat stren

저는 Docker Desktop이 아니라 OrbStack으로 컨테이너들을 띄우고 있습니다.

 

관련 내용은 이 글을 참고해주시기 바랍니다.
Kind와 OrbStack를 사용해서 쉽게 Local에서 Kubernetes 사용하기

클러스터를 배포할 준비를 합니다.

# Create a cluster with kind
kind create cluster

# 클러스터 배포 확인
kind get clusters

myk8s

kubectl cluster-info

Kubernetes control plane is running at https://127.0.0.1:26443
CoreDNS is running at https://127.0.0.1:26443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

# 노드 정보 확인 
kubectl get node -o wide

NAME                  STATUS   ROLES           AGE    VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION                         CONTAINER-RUNTIME
myk8s-control-plane   Ready    control-plane   141d   v1.30.0   192.168.247.2   <none>        Debian GNU/Linux 12 (bookworm)   6.12.15-orbstack-00304-gd0ddcf70447d   containerd://1.7.15
...

# 컨트롤플레인 (컨테이너) 노드 1대가 실행
docker ps
docker images

# kube config 파일 확인
cat ~/.kube/config

# 클러스터 삭제
kind delete cluster

 

진짜로 설정값을 넣어서 클러스터를 생성합니다.

kind create cluster --name myk8s --image kindest/node:v1.31.6 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000
    hostPort: 30000
  - containerPort: 30001
    hostPort: 30001
  - containerPort: 30002
    hostPort: 30002
  - containerPort: 30003
    hostPort: 30003
  kubeadmConfigPatches:
  - |
    kind: ClusterConfiguration
    controllerManager:
      extraArgs:
        bind-address: "0.0.0.0"
    etcd:
      local:
        extraArgs:
          listen-metrics-urls: "http://0.0.0.0:2381"
    scheduler:
      extraArgs:
        bind-address: "0.0.0.0"
  - |
    kind: KubeProxyConfiguration
    metricsBindAddress: "0.0.0.0"
EOF


kind get nodes --name myk8s

myk8s-control-plane

kubens default

Context "kind-myk8s" modified.
Active namespace is "default".

# kind 는 별도 도커 네트워크 생성 후 사용 : 기본값 172.18.0.0/16
docker network ls
NETWORK ID     NAME                              DRIVER    SCOPE
ff79b11006b5   bridge                            bridge    local
91c12d651673   host                              host      local
7a90578a3a56   kind                              bridge    local
a2e20eeb2e52   none                              null      local
625100f715de   traefik-plugin-hands-on_default   bridge    local

docker inspect kind | jq

[
  {
    "Name": "kind",
    "Id": "7a90578a3a56ec00898c824fa6b45706e85d8e5e64a9d489d2742e9c7bb580b7",
    "Created": "2024-09-01T20:16:36.120864157+09:00",
    "Scope": "local",
    "Driver": "bridge",
    "EnableIPv6": true,
    "IPAM": {
      "Driver": "default",
      "Options": {},
      "Config": [
        {
          "Subnet": "192.168.247.0/24",
          "Gateway": "192.168.247.1"
          ...

kubectl cluster-info

Kubernetes control plane is running at https://127.0.0.1:59701
CoreDNS is running at https://127.0.0.1:59701/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

# 노드 정보 확인 : CRI 는 containerd 사용
kubectl get node -o wide
NAME                  STATUS   ROLES           AGE    VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION                         CONTAINER-RUNTIME
myk8s-control-plane   Ready    control-plane   141d   v1.30.0   192.168.247.2   <none>        Debian GNU/Linux 12 (bookworm)   6.12.15-orbstack-00304-gd0ddcf70447d   containerd://1.7.15

# 네임스페이스 확인 >> 도커 컨테이너에서 배운 네임스페이스와 다릅니다!
kubectl get namespaces

# 디버그용 내용 출력에 ~/.kube/config 권한 인증 로드
kubectl get pod -v6

I0225 21:29:32.387575   12488 loader.go:395] Config loaded from file:  /Users/mokpolar/.kube/config
I0225 21:29:32.397525   12488 round_trippers.go:553] GET https://127.0.0.1:59701/api/v1/namespaces/default/pods?limit=500 200 OK in 5 milliseconds
No resources found in default namespace.

 

유용한 툴인 Kube-ops-view 도 설치해줍니다.

# kube-ops-view
# helm show values geek-cookbook/kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set service.main.type=NodePort,service.main.ports.http.nodePort=30000 --set env.TZ="Asia/Seoul" --namespace kube-system

# 설치 확인
kubectl get deploy,pod,svc,ep -n kube-system -l app.kubernetes.io/instance=kube-ops-view

# kube-ops-view 접속 URL 확인 (1.5 , 2 배율)
open "http://127.0.0.1:30000/#scale=1.5"
open "http://127.0.0.1:30000/#scale=2"

Datadog Agent 준비

Datadog API Key 준비

아래 화면과 같이 Datadog Personal Settings에서 API Key, APP Key를 준비해둡니다.

Datadog Agent 설치

이제 클러스터에 Datadog Agent를 설치해줍니다.

 

먼저 Datadog을 Operator 패턴으로 배포해줍니다.

공식 문서를 참고 해주시기 바랍니다. 


아래와 같이 values를 미리 준비한 뒤 설치합니다.

helm repo add datadog https://helm.datadoghq.com
helm show values datadog/datadog-operator > values.yaml

helm install -n mokpolar datadog-operator datadog/datadog-operator -f values.yaml

미리 준비해 둔 API, APP Key로 K8S Secret을 생성합니다.

 

물론 테스트가 아닌 프로덕션 환경에서는 보안상 이런 Key들은 Vault 등에 넣어두는 것이 좋습니다.

kubectl create secret generic datadog-secret --from-literal api-key=<DATADOG_API_KEY> --from-literal app-key=<DATADOG_APP_KEY>

 

Operator 형태로 배포했기 때문에
CR도 따로 배포해줘야 합니다.

 

secret을 생성한 것에 맞추어 아래와 같이 Datadog Agent도 배포해줍니다.

log 수집을 위해 logCollection도 활성화 해줍니다. 

apiVersion: datadoghq.com/v2alpha1
kind: DatadogAgent
metadata:
  name: datadogdatadi
  namespace: mokpolar
spec:
  global:
    site: "datadoghq.com"
    credentials:
      apiSecret:
        secretName: datadog-secret
        keyName: api-key
  features:
    apm:
      enabled: true
    logCollection:
      enabled: true

 

그러면 daemonset 형태로 Datadog agent가 배포됩니다.

 

아래 표에 안내된 사이트 URL 중에서 내 Datadog 웹사이트 URL과 동일한 것을 찾아 어떤 사이트에 있는지 확인할 수 있습니다.

사이트 사이트 URL 사이트 파라미터 위치
US1 https://app.datadoghq.com datadoghq.com US
US3 https://us3.datadoghq.com us3.datadoghq.com US
US5 https://us5.datadoghq.com us5.datadoghq.com US
EU1 https://app.datadoghq.eu datadoghq.eu 유럽연합(독일)
US1-FED https://app.ddog-gov.com ddog-gov.com US
AP1 https://ap1.datadoghq.com ap1.datadoghq.com 일본

Traefik 준비

이번 테스트는 Traefik에서 나오는 로그를 Datadog으로 전송하여 확인하는 것입니다.

 

앞선 글에서 Traefik의 데이터 전송구조를 살펴 본 적이 있습니다. 참고 부탁드립니다.
Traefik API Gateway 사용시 AWS EKS의 NLB에서 Backend까지의 Flow

 

Traefik의 설치는 아래와 같은 방식으로 진행합니다.

helm repo add traefik https://traefik.github.io/charts
helm repo update
helm install traefik traefik/traefik

 

이번에는 Traefik 설치 시 datadog agent로 metric 데이터를 전송하기 위해 설정을 바꿔줍니다.
아래와 같은 형태입니다.

   datadog:
     ## address는 datadog-agent에 메트릭을 전송하도록 지시합니다.
     ## address에서는 datadog agent의 내부 주소를 작성합니다. 
     address: "http://datadog-agent.mokpolar.svc.cluster.local:8125" #"127.0.0.1:8125"
     ## 메트릭을 datadog-agent에 푸시하는 데 사용되는 간격. 기본값=10s
     pushInterval: 10s
     ## 메트릭 수집에 사용할 접두사. 기본값="traefik"
     prefix: traefik
     ## 엔트리 포인트에 메트릭을 활성화합니다. 기본값=true
     addEntryPointsLabels: true
     ## 라우터에 메트릭을 활성화합니다. 기본값=false
     addRoutersLabels: true
     ## 서비스에 메트릭을 활성화합니다. 기본값=true
     addServicesLabels: true

 

Traefik 에서 로그 남기기

 

배포된 Traefik pod에서 원하는 로그를 남기기 위해서는
Custom Plugin으로 Traefik의 플러그인 코드를 일부 수정할 수 있습니다.
GitHub - traefik/plugindemo: This repository includes an example plugin, for you to use as a reference for developing your own plugins

 

위의 Repo를 참고하여 plugin 코드를 일부 수정해주겠습니다.
위 Repo의 README에 나와있듯이, 아래와 같은 파일 구조에서 demo.go의 내용을 일부 수정해주면 됩니다.

./plugins-local/
    └── src
        └── github.com
            └── traefik
                └── plugindemo
                    ├── demo.go
                    ├── demo_test.go
                    ├── go.mod
                    ├── LICENSE
                    ├── Makefile
                    └── readme.md

 

대신에 호출이 들어올 때 마다 로그를 남기도록 아래와 같은 부분을 추가해주면 됩니다.

MyLogger := log.New(os.Stdout, "MYLOG: ", log.LstdFlags)
MyLogger.Print("This is print stdout from logger")

 

 

혹은 더 쉬운 방법으로 그냥 기존에 있는 Plugin을 사용해서 배포해볼 수도 있습니다.
Plugins로 접근해서 API Key Auth by Septima를 사용해봅니다.

 

plugin을 적용하고 Middleware에 API Key를 박은 뒤 호출해봅니다.

 

Traefik을 다시 배포 한 뒤
Traefik pod에 로그가 남도록 호출해줍니다.

curl -X POST \
-H "Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXX" \
"http://localhost:9898/vector" \
-d "{\"message\": \"timestamp:, random\"}" 

 

아래와 같은 구조가 됩니다.



그러면 Traefik pod에는 이런 로그가 Traefik pod에 남는걸 볼 수 있습니다.

 

그러면 Datadog 화면에서도 해당 로그를 확인해볼 수 있습니다.

References

반응형