쿠버네티스의 Etcd 살펴보기

etcd는 쿠버네티스 클러스터의 중요한 컴포넌트로서, 클러스터의 상태를 저장하고 있습니다. 클러스터에 필요한 설정 정보와, 포드와 서비스 같은 각 리소스들의 명세와 상태 정보 등을 저장하고 있습니다. 이 글에서는 etcd가 이러한 정보들을 어떻게 저장하는지에 대해서 간단히 알아볼 것입니다.

etcd

etcd 는 분산 시스템에서 사용할 수 있는 분산형 키-값 (key-value) 저장소 입니다 CoreOS에서 클러스터를 관리하기 위해서 사용했으며, 요즘은 쿠버네티스의 기본 데이터 저장소로 많이 사용하고 있습니다. etcd는 고가용성을 위하여 클러스터로 설치됩니다. 여러 노드의 통신은 래프트(Raft) 알고리즘에 의해 처리합니다. 연결된 노드들 중 리더를 선정하여 클러스터를 관리합니다. 데이터는 분산되어 저장하기 때문에 시스템 오류에 대한 내성을 가지고 있습니다. 클러스터의 노드는 홀수개로 이루어져야 하며, 최소 3개 이상의 노드가 필요합니다.

http://thesecretlivesofdata.com/raft/ 에서 래프트 알고리즘의 작동 방식을 설명하는 애니메이션을 볼 수 있습니다.

쿠버네티스의 etcd

쿠버네티스는 etcd를 기본 데이터 저장소로 사용합니다. 그래서 쿠버네티스를 설치하기 위해서는 etcd 가 필요합니다. 별도의 etcd 클러스터를 쿠버네티스 외부에 설치한 후 쿠버네티스에서 사용할 수 있습니다. 또는 쿠버네티스를 설치할때 컨트롤플레인 노드에 etcd를 포드로 같이 설치할 수 있습니다.

etcd 클러스터를 별도로 설치한 경우

다음은 그림은 etcd 클러스터를 외부에 설치한 경우를 나타낸 것입니다. 쿠버네티스 외부에 etcd 클러스터가 존재하고 kube-apiserver에서 해당 etcd 클러스터에 접속하여 데이터를 저장하고 읽어옵니다.

etcd 클러스터를 컨트롤 플레인 노드에 포드를 설치한 경우

다음 그림은 etcd 클러스터를 쿠버네티스 컨트롤 플레인 노드에 같이 설치한 경우를 나타낸 것입니다. 컨트롤 플레인 노드에 스태틱 포드(static pod) 형태로 etcd가 실행됩니다.

etcd 데이터 흐름 살펴보기

다음 명령어를 실행하여 포드를 생성해 보겠습니다.

$ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.19.2
EOF

다음 그림은 포드를 생성했을 때 일어나는 일을 간단히 나타낸 것입니다.

  • 작성한 매니페스트는 kubectl 를 이용하여 kube-apiserver로 전달합니다.
  • kube-apiserver 는 포드를 생성하는 요청을 받은 후, 포드의 매니페스트를 etcd로 저장합니다.
  • kube-schedulerkube-apiserver 를 통해 포드 정보를 감시(watch)하고 있다가, 새로운 포드가 등록 된것을 감지하고, 포드가 실행 가능한 노드로 배치합니다. 포드의 정보에 배치될 노드의 정보를 추가한 후,kube-apiserver 를 통해 정보를 업데이트 합니다. kube-apiserver 는 업데이트 된 정보를 다시 etcd에 저장합니다.
  • kubelet 은 자신의 노드에 배치된 파드의 정보를 감지하고, 컨테이너를 실행시킵니다. 그리고, kube-apiserver 를 통해 상태 정보를 업데이트 합니다. kube-apiserver 는 업데이트 된 정보를 다시 etcd에 저장합니다.

쿠버네티스에서 etcd 정보 조회하기

쿠버네티스에서 사용되고 있는 etcd의 데이터를 조회하는 방법에 대해서 알아보겠습니다.

예제에 사용하는 쿠버네티스는 etcd가 컨트롤 플레인 노드에 스태틱 포드(static pod)로 같이 설치된 클러스터입니다.

쿠버네티스 클러스터가 정상적으로 설치되었다면, kube-system 네임스페이스에서 etcd 포드를 확인할 수 있습니다. 포드 이름은 일반적으로 etcd-노드명 입니다.

$ kubectl -n kube-system get pod
NAME                              READY   STATUS                   RESTARTS   AGE
...
etcd-node001                      1/1     Running                  0          229d
etcd-node002                      1/1     Running                  0          229d
etcd-node003                      1/1     Running                  1          229d
...

미러 포드(mirror pod)로 등록되어 있다면, etcd 포드를 확인할 수 있습니다.

etcdctl 사용하기

etcd 포드들 중 하나에 ps aux 명령어를 실행하여 etcd 서버의 주소를 확인해 보겠습니다.

$ kubectl -n kube-system exec -it etcd-node001 -- ps aux

PID   USER     TIME  COMMAND
    1 root      9d20 etcd --advertise-client-urls=https://10.203.163.116:2379,h
39283 root      0:00 ps aux

--advertise-client-urls 플래그의 값을 사용하여, etcd 클러스터에 명령을 실행해 보겠습니다. etcd 클러스터에 명령을 실행하기 위해서 etcdctl 이라는 유틸리티를 사용하겠습니다.

etcd의 데이터를 파일로 저장하기

etcdctl 실행할 때, v3 API를 사용하기 위해 ETCDCTL_API=3 을 붙입니다. 그리고, 접속 주소랑 인증을 위한 인증서 파일 경로를 플래그로 넘겨줍니다.

다음은 etcd에 저장된 데이터를 json 형식으로 저장하는 예제입니다.

$ ADVERTISE_URL="<https://10.203.163.116:2379>"

$ kubectl -n kube-system exec etcd-node001 -- sh -c \\
"ETCDCTL_API=3 etcdctl \\
--endpoints $ADVERTISE_URL \\
--cacert /etc/kubernetes/pki/etcd/ca.crt \\
--key /etc/kubernetes/pki/etcd/server.key \\
--cert /etc/kubernetes/pki/etcd/server.crt \\
get \\"\\" --prefix=true -w json" > etcd-data.json

저장된 데이터를 조회해 보기

다음은 etcd-data.json 파일의 일부분입니다. 파일을 살펴보면, 키와 값의 목록으로 이루어져 있는것을 알 수 있습니다. 키와 값들은 base64로 인코딩 되어 있기 때문에, 쉽게 알아 볼 수 없습니다.

{
  "header": {
    "cluster_id": 17306099881785348000,
    "member_id": 17264302005967186000,
    "revision": 66544117,
    "raft_term": 2
  },
  "kvs": [
    {
      "key": "L3JlZ2lzdHJ5L2FwaWV4dGVuc2lvbnMuazhzLmlvL2N1c3RvbXJlc291cmNlZGVmaW5pdGlvbnMvYWRhcHRlcnMuY29uZmlnLmlzdGlvLmlv",
      "create_revision": 6490,
      "mod_revision": 30436184,
      "version": 4,
      "value": "eyJraW5kIjoiQ3VzdG9tUmVzb3VyY2VEZWZpbml0aW9uIiwiYXBpVmVyc2lvbiI6ImFwaWV4dGVuc2lvbnMuazhzLmlvL3YxYmV0YTEi...생략..."
    },
    {
      "key": "L3JlZ2lzdHJ5L2FwaWV4dGVuc2lvbnMuazhzLmlvL2N1c3RvbXJlc291cmNlZGVmaW5pdGlvbnMvYXBpa2V5cy5jb25maWcuaXN0aW8uaW8=",
      "create_revision": 11406824,
      "mod_revision": 11406826,
      "version": 3,
      "value": "eyJraW5kIjoiQ3VzdG9tUmVzb3VyY2VEZWZpbml0aW9uIiwiYXBpVmVyc2lvbiI6ImFwaWV4dGVuc2lvbnMuazhzLmlvL3YxYmV0YTEiLCJtZXRhZGF0YSI6eyJuYW1lIjoiYXBpa2V5cy5jb25maWcuaXN0aW8uaW8iLCJ1aWQiOiJhMWFjMGZhMi0yZWM1LTQ1MzMtOGViOC1mZDMwY2JlMjQ0ZDgiLCJn...생략..."
    },
...

다음 명령어를 실행하면, 디코딩된 키값들을 조회해 볼 수 있습니다.

$ for k in $(cat etcd-data.json | jq '.kvs[].key' | cut -d '"' -f2); do echo $k | base64 --decode; echo; done

쿠버네티스의 전체 리소스들을 확인할 수 있습니다.

...
/registry/pods/istio-system/istio-citadel-58c6fb56fb-fs2gp
/registry/pods/istio-system/istio-egressgateway-64787c7b7d-7fblz
/registry/pods/istio-system/istio-galley-67f97d7c8b-wgb2r
/registry/pods/istio-system/istio-grafana-post-install-1.2.10-sl54z
/registry/pods/istio-system/istio-ingressgateway-66cd7b9b8b-hbfsl
...
/registry/services/endpoints/istio-system/istio-citadel
/registry/services/endpoints/istio-system/istio-egressgateway
/registry/services/endpoints/istio-system/istio-galley
/registry/services/endpoints/istio-system/istio-ingressgateway
...

nginx 포드의 리소스

앞서 예제에 있는 포드를 생성한 다음, etcd 데이터를 저장하였다면 다음과 같은 리소스들의 키 정보도 확인할 수 있습니다. 해당 포드의 이벤트 리소스와 포드 리소스 입니다.

/registry/events/default/nginx.1630e320224081de
/registry/events/default/nginx.1630e320535d4dd0
/registry/events/default/nginx.1630e32218d6d691
/registry/events/default/nginx.1630e3221ea631fb
/registry/events/default/nginx.1630e322284c4b56
...
/registry/pods/default/nginx

포드의 이벤트는 kubectl describe pod 포드네임 명령어를 이용하여 확인해 볼 수 있습니다.

$ kubectl describe pod nginx

“Events:”라는 부분에 포드 관련 이벤트가 조회되는 것을 확인할 수 있습니다. 이 이벤트는 시간이 지나면 자동으로 삭제되기 때문에, 안 보일수도 있습니다. (이벤트 지속 시간의 기본 설정 값은 1시간입니다.)

Name:         nginx
Namespace:    default
Priority:     0
...
Events:
  Type    Reason     Age    From                 Message
  ----    ------     ----   ----                 -------
  Normal  Scheduled  2m37s  default-scheduler    Successfully assigned default/nginx to worker-001
  Normal  Pulling    2m36s  kubelet, worker-001  Pulling image "nginx:1.19.2"
  Normal  Pulled     2m28s  kubelet, worker-001  Successfully pulled image "nginx:1.19.2"
  Normal  Created    2m28s  kubelet, worker-001  Created container nginx
  Normal  Started    2m28s  kubelet, worker-001  Started container nginx

특정 키로 조회해보기

특정 키의 값을 바로 조회해 볼 수도 있습니다. etcdctl 의 get 플래그에 키를 지정하면 됩니다. default 네임스페이스에 있는 nginx 라는 포드의 정보를 조회해 보겠습니다.

KEY="/registry/pods/default/nginx"

kubectl -n kube-system exec etcd-node001 -- sh -c \\
"ETCDCTL_API=3 etcdctl \\
--endpoints $ADVERTISE_URL \\
--cacert /etc/kubernetes/pki/etcd/ca.crt \\
--key /etc/kubernetes/pki/etcd/server.key \\
--cert /etc/kubernetes/pki/etcd/server.crt \\
get \\"$KEY\\" -w json" | jq '.kvs[].value' | cut -d '"' -f2 | base64 --decode

다음은 조회된 결과 입니다. 포드의 정보를 가지고 있는것을 확인할 수 있습니다. 문자열 데이터가 아닌 부분은 깨져 보이지만, 대충 어떤 의미를 가지는지는 확인할 수 있습니다.

k8s

v1Pod�
�
nginxdefault"*$1ae7d990-d09e-443b-a419-0d8bbc0ece232���b�
0kubectl.kubernetes.io/last-applied-configuration�{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"nginx","namespace":"default"},"spec":{"containers":[{"image":"nginx:1.19.2","name":"nginx"}]}}
z�
1
default-token-pz9rt2
default-token-pz9rt��
nginx
     nginx:1.19.2*BJJ
default-token-pz9rt-/var/run/secrets/kubernetes.io/serviceaccount"2j/dev/termination-logr
                                                                                         IfNotPresent����FileAlways 2
                                                                                                                     ClusterFirstBdefaultJdefaultRworker-001X`hr���default-scheduler�6
node.kubernetes.io/not-readyExists"	NoExecute(��8
node.kubernetes.io/unreachableExists"	NoExecute(�����
Running#

InitializedTru���*2
ReadyTru���*2'
ContainersReadyTru���*2$

PodScheduledTru���*2"*
                      10.233.166.02
                                   172.32.8.8���B�
nginx

��� (2
      nginx:1.19.2:_docker-pullable://nginx@sha256:b0ad43f7ee5edbc0effbc14645ae7055e21bc1973aee5150745632a24a752661BIdocker://9e8f506939d41129f61720813ee9cda07569e6628cf385fa71b692425d4be40cJ
BestEffortZ"

이상으로 etcd에 대해서 간단히 살펴보았습니다.

Prometheus Operator로 etcd 모니터링 하기

etcd 모니터링 하기

etcd는 /metrics 라는, 프로메테우스가 수집할 수 있는 매트릭 엔드 포인트를 제공한다. 하지만, Secure Etcd 클러스터인 경우에는 해당 엔드 포인트에 접근하기 위해서는 인증서가 필요하다.

(다른 방법으로는 /metrics 엔드 포인트를 다른 포트로 분리하여, 인증서 없이 접근할 수도 있다. --listen-metrics-urls 옵션을 참고 바란다.)

환경

helm을 사용해서 prometheus-operator를 설치할 것이다. 그래서 prometheus-operator를 설치할때, etcd를 모니터링하도록 설정 파일을 변경해서 사용한다.

values.yaml 수정하기

kubeEtcd

kubeEtcd.serviceMonitor의 값들을 변경한다. scheme를 https로 변경하고, 인증서 정보를 등록한다.

## Component scraping etcd
##
kubeEtcd:
...
  serviceMonitor:
    scheme: https
    insecureSkipVerify: false
    serverName: localhost
    caFile: /etc/prometheus/secrets/etcd-client-cert/etcd-ca
    certFile: /etc/prometheus/secrets/etcd-client-cert/etcd-client
    keyFile: /etc/prometheus/secrets/etcd-client-cert/etcd-client-key
...

prometheus

프로메테우스를 기동할때 etcd-client-cert란 이름의 secret를 pod에 마운트하기 위해서, prometheus.secrets에 etcd-client-cert를 추가해 준다. 그리고, etcd 스크랩 설정 추가를 위해서, prometheus.additionalScrapeConfigs의 kube-etcd 부분을 활성화 해준다

## Deploy a Prometheus instance
##
prometheus:
...
    secrets:
      - "etcd-client-cert"

...

    additionalScrapeConfigs:
      - job_name: kube-etcd
        kubernetes_sd_configs:
          - role: node
        scheme: https
        tls_config:
          ca_file:   /etc/prometheus/secrets/etcd-client-cert/etcd-ca
          cert_file: /etc/prometheus/secrets/etcd-client-cert/etcd-client
          key_file:  /etc/prometheus/secrets/etcd-client-cert/etcd-client-key
        relabel_configs:
        - action: labelmap
          regex: __meta_kubernetes_node_label_(.+)
        - source_labels: [__address__]
          action: replace
          target_label: __address__
          regex: ([^:;]+):(\d+)
          replacement: ${1}:2379
        - source_labels: [__meta_kubernetes_node_name]
          action: keep
          regex: .*mst.*
        - source_labels: [__meta_kubernetes_node_name]
          action: replace
          target_label: node
          regex: (.*)
          replacement: ${1}
        metric_relabel_configs:
        - regex: (kubernetes_io_hostname|failure_domain_beta_kubernetes_io_region|beta_kubernetes_io_os|beta_kubernetes_io_arch|beta_kubernetes_io_instance_type|failure_domain_beta_kubernetes_io_zone)
          action: labeldrop
          
...

인증서 복사하기

etcd 인증서를, 프로메테스를 설치할 monitoring 네임스페이스에, etcd-client-cert란 이름의 secret로 복사한다.

POD_NAME=$(kubectl get pods -o=jsonpath='{.items[0].metadata.name}' -l component=kube-apiserver -n kube-system)

kubectl create secret generic etcd-client-cert -n monitoring \
  --from-literal=etcd-ca="$(kubectl exec $POD_NAME -n kube-system -- cat /etc/kubernetes/pki/etcd/ca.crt)" \
  --from-literal=etcd-client="$(kubectl exec $POD_NAME -n kube-system -- cat /etc/kubernetes/pki/etcd/healthcheck-client.crt)" \
  --from-literal=etcd-client-key="$(kubectl exec $POD_NAME -n kube-system -- cat /etc/kubernetes/pki/etcd/healthcheck-client.key)"

helm으로 prometheus-operator 설치하기

helm 설치 명령어로, proemtheus-operator를 설치한다. 수정한 설정값을 적용하기 위해서 --values values.yaml 옵션을 사용한다.

helm install stable/prometheus-operator --name mon --namespace monitoring --values values.yaml --tls

참고 사항

helm으로 prometheus-operator를 삭제할때, crd는 자동으록 삭제되지 않는다. 아래 명령어로 직접 삭제해야한다.

kubectl delete --ignore-not-found customresourcedefinitions \
  prometheuses.monitoring.coreos.com \
  servicemonitors.monitoring.coreos.com \
  podmonitors.monitoring.coreos.com \
  alertmanagers.monitoring.coreos.com \
  prometheusrules.monitoring.coreos.com

Prometheus Operator로 etcd 모니터링 하기

 1 분 소요

etcd 모니터링 하기

etcd는 /metrics 라는, 프로메테우스가 수집할 수 있는 매트릭 엔드 포인트를 제공한다. 하지만, Secure Etcd 클러스터인 경우에는 해당 엔드 포인트에 접근하기 위해서는 인증서가 필요하다.

(다른 방법으로는 /metrics 엔드 포인트를 다른 포트로 분리하여, 인증서 없이 접근할 수도 있다. --listen-metrics-urls 옵션을 참고 바란다.)

환경

helm을 사용해서 prometheus-operator를 설치할 것이다. 그래서 prometheus-operator를 설치할때, etcd를 모니터링하도록 설정 파일을 변경해서 사용한다.

values.yaml 수정하기

kubeEtcd

kubeEtcd.serviceMonitor의 값들을 변경한다. scheme를 https로 변경하고, 인증서 정보를 등록한다.

## Component scraping etcd
##
kubeEtcd:
...
  serviceMonitor:
    scheme: https
    insecureSkipVerify: false
    serverName: localhost
    caFile: /etc/prometheus/secrets/etcd-client-cert/etcd-ca
    certFile: /etc/prometheus/secrets/etcd-client-cert/etcd-client
    keyFile: /etc/prometheus/secrets/etcd-client-cert/etcd-client-key
...

prometheus

프로메테우스를 기동할때 etcd-client-cert란 이름의 secret를 pod에 마운트하기 위해서, prometheus.secrets에 etcd-client-cert를 추가해 준다. 그리고, etcd 스크랩 설정 추가를 위해서, prometheus.additionalScrapeConfigs의 kube-etcd 부분을 활성화 해준다.

## Deploy a Prometheus instance
##
prometheus:
...
    secrets:
      - "etcd-client-cert"

...

    additionalScrapeConfigs:
      - job_name: kube-etcd
        kubernetes_sd_configs:
          - role: node
        scheme: https
        tls_config:
          ca_file:   /etc/prometheus/secrets/etcd-client-cert/etcd-ca
          cert_file: /etc/prometheus/secrets/etcd-client-cert/etcd-client
          key_file:  /etc/prometheus/secrets/etcd-client-cert/etcd-client-key
        relabel_configs:
        - action: labelmap
          regex: __meta_kubernetes_node_label_(.+)
        - source_labels: [__address__]
          action: replace
          target_label: __address__
          regex: ([^:;]+):(\d+)
          replacement: ${1}:2379
        - source_labels: [__meta_kubernetes_node_name]
          action: keep
          regex: .*mst.*
        - source_labels: [__meta_kubernetes_node_name]
          action: replace
          target_label: node
          regex: (.*)
          replacement: ${1}
        metric_relabel_configs:
        - regex: (kubernetes_io_hostname|failure_domain_beta_kubernetes_io_region|beta_kubernetes_io_os|beta_kubernetes_io_arch|beta_kubernetes_io_instance_type|failure_domain_beta_kubernetes_io_zone)
          action: labeldrop
          
...

인증서 복사하기

etcd 인증서를, 프로메테스를 설치할 monitoring 네임스페이스에, etcd-client-cert란 이름의 secret로 복사한다.

POD_NAME=$(kubectl get pods -o=jsonpath='{.items[0].metadata.name}' -l component=kube-apiserver -n kube-system)

kubectl create secret generic etcd-client-cert -n monitoring \
  --from-literal=etcd-ca="$(kubectl exec $POD_NAME -n kube-system -- cat /etc/kubernetes/pki/etcd/ca.crt)" \
  --from-literal=etcd-client="$(kubectl exec $POD_NAME -n kube-system -- cat /etc/kubernetes/pki/etcd/healthcheck-client.crt)" \
  --from-literal=etcd-client-key="$(kubectl exec $POD_NAME -n kube-system -- cat /etc/kubernetes/pki/etcd/healthcheck-client.key)"

helm으로 prometheus-operator 설치하기

helm 설치 명령어로, proemtheus-operator를 설치한다. 수정한 설정값을 적용하기 위해서 --values values.yaml 옵션을 사용한다.

helm install stable/prometheus-operator --name mon --namespace monitoring --values values.yaml --tls

참고 사항

helm으로 prometheus-operator를 삭제할때, crd는 자동으록 삭제되지 않는다. 아래 명령어로 직접 삭제해야한다.

kubectl delete --ignore-not-found customresourcedefinitions \
  prometheuses.monitoring.coreos.com \
  servicemonitors.monitoring.coreos.com \
  podmonitors.monitoring.coreos.com \
  alertmanagers.monitoring.coreos.com \
  prometheusrules.monitoring.coreos.com

참고 링크

  • https://github.com/helm/charts/tree/master/stable/prometheus-operator
  • https://github.com/kubernetes-monitoring/kubernetes-mixin
  • https://github.com/etcd-io/etcd/blob/master/Documentation/op-guide/monitoring.md

etcd 명령어 예제

인증서 기반

TLS 인증서 기반으로 etcd를 설치한 경우, etcdctl을 사용하려면, 인증서 정보를 플래그로 넘겨줘야 합니다. 그리고 버전 3의 API를 사용하려면 ETCDCTL_API=3을 선언해줘야 합니다.

ETCDCTL_API=3 etcdctl --endpoints=https://[127.0.0.1]:2379 \
    --cacert=/etc/kubernetes/pki/etcd/ca.crt \
    --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
    --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \
    get foo

명령어가 상당히 길기 때문에, alias로 지정해 놓고 사용하면 편리합니다.

alias etcd3ctl="ETCDCTL_API=3 etcdctl --endpoints=https://[127.0.0.1]:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key"

명령어 예제

전체 조회

버전 3 부터는 ls 명령어가 존재하지 않습니다. 전체 목록 같은 것을 조회하려면, --prefix 플래그를 사용할 수 있습니다.

아래와 같이 실행하면, 전체 목록을 조회해 볼 수 있습니다.

$ etcd3ctl get / --prefix --keys-only

...
/registry/deployments/kube-system/coredns
/registry/deployments/kube-system/metrics-server
/registry/deployments/kube-system/tiller-deploy
/registry/deployments/openebs/maya-apiserver
/registry/deployments/openebs/openebs-admission-server
/registry/deployments/openebs/openebs-localpv-provisioner
/registry/deployments/openebs/openebs-provisioner
/registry/deployments/openebs/openebs-snapshot-operator
/registry/deployments/weave/weave-scope-app
...

멤버 조회

$ etcd3ctl member list
67fab7a197a31464, started, etcd-001, https://10.x.x.x:2380, https://10.x.x.x:2379
9ebdbf1241485ebd, started, etcd-002, https://10.y.y.y:2380, https://10.y.y.y:2379
f3aacf2611e12d71, started, etcd-003, https://10.z.z.z:2380, https://10.z.z.z:2379

엔드 포인트 상태

$ etcd3ctl endpoint health
https://[127.0.0.1]:2379 is healthy: successfully committed proposal: took = 1.13549ms

$ etcd3ctl endpoint status
https://[127.0.0.1]:2379, f3aacf2611e12d71, 3.3.10, 4.6 MB, false, 6, 6880100

etcd 모니터링 하기

Metrics Endpoint

각각의 etcd 서버는 클라이언트 접속용 포트의 /metrics 경로를 이용해서 메트릭을 출력해 줍니다. (클라이언트용 기본 포트는 2379 입니다.)

$ curl http://127.0.0.1:2379/metrics

...
tcd_disk_wal_fsync_duration_seconds_count 4.9931728e+07
# HELP etcd_grpc_proxy_cache_hits_total Total number of cache hits
# TYPE etcd_grpc_proxy_cache_hits_total gauge
etcd_grpc_proxy_cache_hits_total 0
# HELP etcd_grpc_proxy_cache_keys_total Total number of keys/ranges cached
# TYPE etcd_grpc_proxy_cache_keys_total gauge
etcd_grpc_proxy_cache_keys_total 0
# HELP etcd_grpc_proxy_cache_misses_total Total number of cache misses
# TYPE etcd_grpc_proxy_cache_misses_total gauge
etcd_grpc_proxy_cache_misses_total 0
# HELP etcd_grpc_proxy_events_coalescing_total Total number of events coalescing
# TYPE etcd_grpc_proxy_events_coalescing_total counter
etcd_grpc_proxy_events_coalescing_total 0
# HELP etcd_grpc_proxy_watchers_coalescing_total Total number of current watchers coalescing
# TYPE etcd_grpc_proxy_watchers_coalescing_total gauge
etcd_grpc_proxy_watchers_coalescing_total 0
# HELP etcd_mvcc_db_total_size_in_bytes Total size of the underlying database physically allocated in bytes.
# TYPE etcd_mvcc_db_total_size_in_bytes gauge
etcd_mvcc_db_total_size_in_bytes 1.0145792e+07
# HELP etcd_mvcc_db_total_size_in_use_in_bytes Total size of the underlying database logically in use in bytes.
# TYPE etcd_mvcc_db_total_size_in_use_in_bytes gauge
etcd_mvcc_db_total_size_in_use_in_bytes 4.77184e+06
...

하지만 TLS 인증 기반으로 etcd를 설치했을 경우, 단순히 매트릭을 보기 위해서도 인증서가 필요합니다. 이런 불편한 때문에 etcd v3.3.0 부터는 별도의 /metrics 엔드포인트를 지정할 수 있는 기능이 생겼습니다. 엔드포인트를 지정할 수 있는 가장 쉬운 방법은 바로 --listen-metrics-urls 플래그 입니다. 또 다른 방법으로는 환경 변수나, 설정 파일에 ETCD_LISTEN_METRICS_URLS 값을 설정하는 것입니다.

예를 들어 --listen-metrics-urls=http://0.0.0.0:2381 플래그를 etcd를 실행 할 때 추가하면, 2381 포트로 /metrics/health 를 조회해 볼 수 있습니다.

Health Endpoint

/health 엔드포인트를 이용하면, etcd 서버의 상태를 알 수 있습니다.

$ curl http://127.0.0.1:2379/health
{"health":"true"}

Prometheus

프로메테우스 설정 파일에, etcd 스크랩 설정을 추가하면, 프로메테우스가 etcd의 메트릭 엔드포인트에 접근하여, 메트릭 데이터를 수집해 갑니다.

scrape_configs:
  - job_name: etcd
    static_configs:
    - targets: ['x.x.x.x:2381','y.y.y.y:2381','z.z.z.z:2381']

참고 문서