[DevOps] k8s monitoring with Datadog
안녕하세요? 정리하는 개발자 워니즈 입니다. 이번시간에는 올해 가장 뿌듯하면서도 성취감 있었던 일중 하나인 datadog모니터링 도입기에 대해서 정리를 하고자 합니다.
현재 진행중인 프로젝트는 Java기반의 Spring Boot로 된 서비스를 개발/운영중입니다. APM(Application Performance Monitoring)을 위해서 기존에는 pinpoint를 사용하고있었지만, 다소 부족한 기능과 전체적인 서비스 가시성을 확보하지 못하여, 상용 솔루션인 Datadog를 도입하기로 하였습니다.
1. Datadog Agent 소개
데이터독을 통해서 그러면 어떠한 내용들을 확인 할 수 있을까요? k8s Cluster와 관련된 모든 정보를 확인할 수 있습니다.
- Cluster Node의 가시성 확보
- POD / Container 레벨의 가시성 확보
- Kubernetes Event 수집
- Application의 Trace 정보 수집
그러면 각 Layer 별로 수집을 하기 위해서 어떤 내용이 필요한지 정리해보도록 하겠습니다.
Datadog의 내용들은 공식 Blog에서도 확인할 수 있습니다.
Kubelet에서 노드 수준 데이터 수집
Datadog 에이전트는 각 worker node에서 kubelet을 모니터링하여 컨테이너가 어떻게 동작하는지에 대한 모든 메트릭들을 수집합니다.
API 서버에서 클러스터 수준 데이터 수집
Datadog 에이전트는 Kubernetes API 서버에 개별적으로 쿼맇아ㅕ 특정 구성 요소의 동작에 대한 데이터를 수집하고 클러스터 전체에 대한 주요 메타데이터를 수집합니다. 이 설정은 클러스터의 규모가 커지면 커질수록 API 서버 및 etcd에 대한 로드를 증가 시켰습니다.
Datadog 클러스터 에이전트를 통한 분산
클러스터 에이전트는 API 서버와 노드 기반 에이전트 간의 프록시 역할을 합니다. 이는 API 서버의 직접 부하를 완화할 뿐만 아니라 노드 기반 에이전트가 노드 수준 데이터 수집에 집중할 수 있도록 하는 반면 클러스터 에이전트는 Control Plane에서 클러스터 수준 데이터를 수집합니다.
정리를 하면 다음과 같습니다.
- datadog-agent : 데이터독 에이전트는 각 노드의 메트릭, 분산 추적 및 로그를 수집하고 서버 리소스(CPU, Memory등) 메트릭을 자동으로 수집
- datadog-kube-state-metrics-agent : Kubernetes API를 감시하여 객체의 상태에 대한 메트릭을 수집.
- datadog-cluster-agent : node agent에서 Master노드의 API 서버에 직접 쿼리를 하게되면 클러스터 증가시 Master노드의 API서버 및 etcd에 대한 로그가 증가하기 때문에 Master 노드의 서버 부하를 줄이기 위해 API서버와 node agent간의 프록시 역할을 한다.
2. Datadog Agent 설치
사용자 지정 릴리스 이름으로 차트를 설치하려면 RELEASE_NAME
(예: datadog-agent
):
- Helm 를 설치합니다 .
- Datadog Helm 저장소를 추가합니다.
helm repo add datadog https://helm.datadoghq.com
- 새로 추가된 차트의 최신 버전 가져오기:
helm repo update
. - 빈 values.yaml 파일을 만들고 원하는 경우 기본값 을 재정의합니다 . 여기 에서 몇 가지 예를 찾을 수 있습니다 .
- Datadog 에이전트를 배포합니다.
helm install RELEASE_NAME -f datadog-values.yaml --set datadog.site='datadoghq.com' --set datadog.apiKey= datadog/datadog
targetSystem: "linux"
datadog:
apiKey: 'sample'
appKey: 'sample'
clusterName: 'test-k8s'
tags: []
kubelet:
tlsVerify: "false"
logs:
enabled: false
containerCollectAll: false
containerCollectUsingFiles: false
apm:
portEnabled: true
socketPath: /var/run/datadog/apm.socket
hostSocketPath: /var/run/datadog/
processAgent:
enabled: false
processCollection: false
systemProbe:
enableTCPQueueLength: false
enableOOMKill: false
collectDNSStats: false
설치 현황
datadog-agent-2dvkn 3/3 Running 0 95d
datadog-agent-2jkdh 3/3 Running 0 95d
datadog-agent-5q595 3/3 Running 0 95d
datadog-agent-6gnnd 3/3 Running 0 95d
datadog-agent-6pxn7 3/3 Running 0 39d
datadog-agent-7kwpl 3/3 Running 0 95d
datadog-agent-875rt 3/3 Running 0 95d
datadog-agent-8sbjr 3/3 Running 0 95d
datadog-agent-9c6d6 3/3 Running 0 39d
datadog-agent-cluster-agent-84bd789556-cff7d 1/1 Running 0 95d
datadog-agent-kube-state-metrics-fb456b9bf-hqn2p 1/1 Running 0 95d
....
위와 같이 dd-agent들은 각 노드별로, cluster-agent, kube-state-metric은 하나의 특정 node에 설치가 됩니다.
3. Helm Chart 수정(APM 설정)
상위 설정까지 마치게 되면, 아래의 정보까지는 자동으로 수집이 되게 됩니다.
- Cluster Node의 가시성 확보
- POD / Container 레벨의 가시성 확보
- Kubernetes Event 수집
그럼 이제 APM에 대한 설정을 정리해보겠습니다.
- Application의 Trace 정보 수집
APM을 설정하기 위해서는 Application이 기동할 때, 사용되어야 할 내용들이 있습니다.
apiVersion: apps/v1
kind: Deployment
metadata:
....
## volume을 정의 합니다.
## 1) dd-apm-agent mount를 위한 container volume
## 2) apmsocket을 위한 hostpath volume
spec:
{{- if (ne .Values.phase "test") }}
volumes:
- name: datadog-apm-agent
emptyDir: {}
- hostPath:
path: /var/run/datadog/
name: apmsocketpath
{{- end }}
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: networkType
operator: DoesNotExist
containers:
- name: {{ .Values.phase }}-{{ .Values.projectName }}
image: {{ .Values.dockerImgName }}:{{ .Values.deployImgVersion }}
## volume을 mount 합니다.
## 1) dd-apm-agent mount를 위한 container volume
## 2) apmsocket을 위한 hostpath volume
{{- if (ne .Values.phase "test") }}
volumeMounts:
- name: datadog-apm-agent
mountPath: /datadog/apm/agent
- name: apmsocketpath
mountPath: /var/run/datadog
{{- end }}
.....
## apm에 대한 셋팅을 합니다.
## 1) DD_ENV, DD_SERVICE, DD_VERSION 은 배포된 환경, 서비스 및 버전에 대한 정보
## 2) DD_TRACE_ENABLED는 APM TRACE 사용 유무
{{- if (ne .Values.phase "alpha") }}
- name: DD_SERVICE
valueFrom:
fieldRef:
fieldPath: metadata.labels['app']
- name: DD_VERSION
valueFrom:
fieldRef:
fieldPath: metadata.labels['version']
- name: DD_ENV
value: {{ .Values.phase }}
- name: DD_TAGS
value : {{ .Values.namespace }}
- name: DD_TRACE_ENABLED
value: "true"
- name: DD_TRACE_SAMPLE_RATE
value: "1"
- name: DD_PROFILING_ENABLED
value: "true"
- name: DD_JMXFETCH_ENABLED
value: "true"
## 어플리케이션 기동시 APM jar 파일을 삽입합니다.
command: ["/bin/sh"]
args: ["-c", "/sbin/tini java -javaagent:/datadog/apm/agent/dd-java-agent.jar $JAVA_OPTS -jar api-gateway.jar"]
{{- end }}
......
{{- if (ne .Values.phase "alpha") }}
## initcontainer를 이용하여 초기 dd-agent-jar파일을 다운받아 container volue을 mount 합니다.
initContainers:
- name: datadog-apm-agent
image: busybox
command:
- wget
- -O
- /datadog/apm/agent/dd-java-agent.jar
- https://dtdg.co/latest-java-tracer
volumeMounts:
- name: datadog-apm-agent
mountPath: /datadog/apm/agent
{{- end }}
위의 과정을 통해서 APM TRACE가 가능해지고, 삽입된 jar파일에서 수집된 정보들은 모두 dd-agent에게 socket을 통하여 전달하게 되고, 모든 내용은 SaaS형태의 Datadog 수집 서버로 전송을 하게 됩니다.
4. Dashboard 작성
필자는 Dashboard를 보고 한 눈에 어플리케이션들의 상황을 알 수 있게끔 구성을 하고 싶었습니다. 그래서 가장 중점적으로 보는 지표를 정해보기로 했습니다.
- Kubernetes 현황
- Kubernetes Contaeinr CPU, Memory
- Kubernetes Events
- Application Error(50*)
- Application Latency(3s 이상)
- Application Request Volume
위의 현황으로도 얼추 어느정도의 어플리케이션 상황들은 볼 수 있다라고 생각이 되었습니다.
붉은색 박스로 표기해놓은 순서대로 위에서 지정한 지표들을 볼 수 있도록 구성했습니다. 실제로 배포시 혹은 특정 이벤트시에 해당 지표들을 매우 잘 활용하고 있으며, 서비스를 안정적으로 운영하는데 많은 기여를 하고 있다고 생각합ㄴ니다.
5. 마치며..
Datadog중에서 Cluster, Pod, Container 레벨까지는 Prometheus, Grafana로 충분히 모니터링이 가능합니다. 하지만, Datadog을 도입한 가장큰 이유중 하나는 APM 기능을 이용하기 위함이였습니다.
무수히 많은 어플리케이션들이 MSA 형태로 배포되어있고 호출을 통해서 서로가 서로에게 연결이 되어있습니다. 이상황에서 연결상에 문제라던지 장애를 맞이하면 어디부분에서 문제가 발생을 했는지 찾기가 굉장히 힘듭니다.
그러한 부분에 있어서 APM 도입을 통해 가장 크게 해소 할 수 있던 것 같고, 특히 성능 개선부분에 있어서도 여러가지 시야를 얻을 수 있었습니다.
6. 참조
https://dev.to/airoasis/kubernetes-datadog-spring-boot-3g34