Kubernetes/Istio 를 위한 Datadog 설정
Tags: kubernetes, istio, datadog
Published: 2022-02-21 04:50:35

Datadog은 Helm 또는 Operator를 통해 설정 가능하다. 여기에도 역시 Operator를 사용한다. Datadog을 통해 Logging, APM, Kubernetes, Istio Monitoring, Alerting 등 많은 기능을 한번에 해결 할 수 있다. (~~하지만 매우 비싸다~~) 예전에 Grafana, Prometheus, AlertManager 등을 사용하여 Monitoring을 구축하였는데... Datadog은 Agent만 설치하면 모든게 가능해진다. 정말 간편하다

## Datadog Operator 설치
우선 Datadog Operator를 Helm을 통해 설치한다. 
https://github.com/DataDog/datadog-operator/blob/main/docs/getting_started.md
```bash
$ helm repo add datadog https://helm.datadoghq.com
$ helm install -n datadog --create-namespace --set fullnameOverride="dd-op" mwp-datadog-operator datadog/datadog-operator
```
이렇게 설치하면 `datadog` namespace에 datadog operator 가 설치된다. 

---
## Datadog Configuration 설정
### Datadog credential 을 Kubernetes Secret으로 생성
Datadog API, APP Key를 이용하여 Kubernetes secret을 생성
```bash
$ kubectl create secret generic datadog-secrets --from-literal api-key=<DATADOG_API_KEY> --from-literal app-key=<DATADOG_APP_KEY>
```
생성된 kubernetes secret을 아래에서 사용

### Datadog Agent 및 Cluster Agent 설치 및 설정
`datadog-operator.yaml` 파일을 생성한다.
```yaml
apiVersion: datadoghq.com/v1alpha1
kind: DatadogAgent
metadata:
  namespace: datadog
  name: datadog
spec:
  credentials:
    apiSecret:
      secretName: datadog-secrets
      keyName: api-key
    appSecret:
      secretName: datadog-secrets
      keyName: app-key
  agent:
    image:
      name: "gcr.io/datadoghq/agent:latest"
    config:
      hostPort: 8125
      collectEvents: true
      tolerations:
        - operator: Exists
      env:
      - name: DD_DOGSTATSD_NON_LOCAL_TRAFFIC # Java JVM Metrics를 받기 위해 필요
        value: "true"
    log:
      enabled: true
      logsConfigContainerCollectAll: true
    apm:
      enabled: true
      hostPort: 8126
    process:
      enabled: true
      processCollectionEnabled: true
    systemProbe:
      bpfDebugEnabled: true
  features:
    kubeStateMetricsCore:
      enabled: true
    networkMonitoring:
      enabled: true
  clusterAgent:
    image:
      name: "gcr.io/datadoghq/cluster-agent:latest"
    config:
      clusterChecksEnabled: true
    replicas: 2
  clusterChecksRunner:
    image:
      name: "gcr.io/datadoghq/agent:latest
    replicas: 2
  clusterName: eks-demo
```
* Datadog agent가 DaemonSet 형태로 각 node 설치된다. 
* Datadog cluster agent도 설치되어 효율적인 운영이 가능하다

설정을 적용한다.
```bash
$ kubectl apply -f datadog-operator.yaml
```

이렇게 적용하고 나면 Datadog agent는 auto discovery를 통해 가능한 모든 metrics를 가져온다. 설정 파일을 보면 알겠지만, kubernetes 로깅, 모니터링, 그리고 application 에 Datadog APM 을 적용하면 port 8126으로 받을 수 있도록 설정을 한다. 

Agent는 DaemonSet 형태로 각 노드에 하나씩 배포된다. 직접 해당 Pod를 `kubectl describe pod datadog-agent-~~~ -n datadog` 확인해보면 `agent`, `trace-agent`, `process-agent`, `system-probe` 이렇게 4개의 container가 올라가 있는걸 볼 수 있다. 

---
## Istio 설정 변경
이렇게 하면 Kubernets monitoring 및 Logging 이 모두 가능해진다. 하지만 Istio 는 제대로 monitoring 되지 않고, Envoy proxy tracing 도 불가능하다. Istio 를 위해 Istio operator 설정을 변경해 주어야 한다. 
https://www.datadoghq.com/blog/how-to-monitor-istiod/#monitoring-istiod-with-datadog

### Istio monitoring을 위한 변경
아래와 같이 Datadog 이 Istio 관련 지표를 모니터링 할 수 있게 수정
```bash
$ kubectl -n istio-system patch service istiod --patch "$(cat<<EOF
metadata:
  annotations:
    ad.datadoghq.com/endpoints.check_names: '["istio"]'
    ad.datadoghq.com/endpoints.init_configs: '[{}]'
    ad.datadoghq.com/endpoints.instances: |
      [
        {
          "istiod_endpoint": "http://%%host%%:15014/metrics",
          "send_histograms_buckets": true
        }
      ]
EOF
)"
```

### Istio tracing 설정
`istio-operator.yaml` 파일을 아래와 같이 수정하여 APM 에서 Envoy proxy tracing 을 가능하게 한다. (Istio 관련 설치 및 설정은 [EKS 에 Istio 설치 및 설정](https://velog.io/@airoasis/eks-istio-install) 참고)

```yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  namespace: istio-system
  name: istiocontrolplane
spec:
  profile: default
  components:
    egressGateways:
    - name: istio-egressgateway
      enabled: true
      k8s:
        hpaSpec:
          minReplicas: 2
    ingressGateways:
    - name: istio-ingressgateway
      enabled: true
      k8s:
        hpaSpec:
          minReplicas: 2
        service:
          type: NodePort
        serviceAnnotations:
          alb.ingress.kubernetes.io/healthcheck-path: /healthz/ready
          alb.ingress.kubernetes.io/healthcheck-port: "32197"
    pilot:
      enabled: true
      k8s:
        hpaSpec:
          minReplicas: 2
  meshConfig:
    enableTracing: true
    defaultConfig:
      holdApplicationUntilProxyStarts: true
      tracing:  # Enable Datadog Tracing
        datadog:
          address: $(HOST_IP):8126
        sampling: 100.0  # 모든 request를 tracing 한다
    accessLogFile: /dev/stdout
    outboundTrafficPolicy:
      mode: REGISTRY_ONLY
```

`meshConfig` 에 위와 같이 Tracing 관련 설정을 추가한다. 이렇게 하면 Istio는 tracing 정보를 각 node 에 DaemonSet 으로 올라가 있는 Datadog Agent로 Tracing 정보를 보내게 된다. 그리고 Agent는 Datadog으로 모든 data를 전송한다. 이제 해당 설정을 반영한다. 
```bash
$ istioctl install -f istio-operator.yaml
```
> sampling rate을 100%로 하였기 때문에 모든 request에 대해 tracing 이 가능해야 한다. 하지만 Istio 버전에 따라 해당 설정을 적용하기 위해 istio-proxy가 올라가 있는 Pod들을 restart 해줘야 하는 경우가 있다. 1.11, 1.12 에서는 바로 적용 되는거 같다. 하지만 1.10 버전에서는 다시 시작해줘야 한다.

### Istio ServiceEntry 설정
만약, Istio 의 mesh 설정 중에 `outboundTrafficPolicy` 의 `mode` 가 `REGISTRY_ONLY` 이고 (default 설정은 `ALLOW_ANY` 이다), Datadog APM 을 사용하여 Java, Go, Python 등과 같은 Application 의 APM 을 사용하려면 반드시 `ServiceEntry`를 추가해서 application pod에서 각 node에 daemonset으로 올라가 있는 datadog agent 의 container 중 하나인 `tracing-agent`로 outbound 가 설정되어야 한다. (이 내용은 Datadog 의 문서에도 없고, Istio 에서도 특별히 명시되어 있지 않다) 이렇게 하지 않으면 절대 APM 을 확인 할수 없다. EKS 기준 손쉽게 할 수 있는 방법은 아래와 같다.
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: internal-ext
spec:
  hosts:
    - ignored.com
  addresses:
    - 192.168.0.0/16
  ports:
    - number: 8126
      name: tcp-datadog
      protocol: TCP
  resolution: NONE
```
> 🤚 팀에서 특별한 이유로 네이버 클라우드를 사용하는 프로젝트가 있는데, 여기에서는 이렇게 모든 설정을 하여도 APM 을 확인할 수 없었다. 그래서 네이버 클라우드와 연락하여 확인해본 결과 네이버 클라우드는 AWS EKS 와 달리 Kubernetes Service의 CNI인 Cilium 을 사용하고 있어서 동작하지 않았던 것이다. 결국 Cilium의 설정을 변경 (`cilium-config`의 `kube-proxy-replacement`를 `disabled` 에서 `probe` 로 변경) 하거나 Datadog의 설정 중 `hostNetwork`를 'true' 로 변경하는 방법이 있다.

---
여기 까지 하면 Datadog 의 APM 에서 Envoy proxy의 tracing 정보를 모두 볼 수 있다. 하지만 이건 istio-proxy의 tracing 정보이고 application 의 APM은 아니다... 물론 Istio는 모든 request가 istio-proxy를 통해 들어가고 나가기 때문에 이에 대한 tracing 은 가능하지만 (Istio 공식문서의 Jaeger tracing과 같은) aplication 자체에 대한 APM을 위해서는 각 language에 맞는 Datadog APM 을 사용해야 한다. 

## Datadog Integration 추가
이제 Datadog 에 로그인 하여 Integration tab으로 가서 Kubernetes 및 Istio를 추가해 주면 관련 모니터링을 위한 Dashboard가 추가된다. 

Kubernetes Overview
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/066n2v114y6jsufpk23b.png)

Log
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3qcmkrt6ezz3uhqhpt4i.png)