티스토리 뷰

728x90
반응형

실습 환경

[k8s]kubeadm, kubelet, kubectl을 설치하여 쿠버네티스(kubernetes) 클러스터 구축하기



모니터링 기본 구조

CAdvisor는 컨테이너에 관련된 모니터링 데이터를 확인할 수 있는 모니터링 도구입니다. 하지만 CAdvisor가 제공하는 웹 UI에서는 단기간의 메트릭만 제공할 뿐, 체계적으로 데이터를 저장하고 분석하지는 않습니다.

example

CAdvisor 같은 모니터링 에이전트 부류의 도구들은 /metrics라고 하는 경로를 외부에 노출시켜 제공합니다. 이 /metrics 경로로 요청을 보내면 CAdvisor는 키-값 쌍으로 구성된 메트릭 데이터의 목록을 반환하는데, 이 메트릭 데이터를 프로메테우스 같은 시계열 데이터베이스에 저장할 수 있습니다. 프로메테우스는 CAdvisor의 엔드포인트를 미리 지정해주면 CAdvisor의 /metrics에 접근해 자동으로 데이터를 수집하므로 CAdvisor의 데이터를 직접 프로메테우스에 저장할 필요가 없습니다. 단, 이를 위해서는 프로메테우스가 CAdvisor에 접근해 메트릭을 가져갈 수 있도록 CAdivisor의 엔드포인트 정보를 프로메테우스에 미리 지정해둬야 합니다.

이처럼 /metrics 경로를 외부에 노출시켜 데이터를 수집할 수 있도록 인터페이스를 제공하는 서버를 일반적으로 exporter라고 합니다. exporter에는 다양한 종류가 존재할 수 있습니다. 예를 들어, 애플리케이션 내부의 데이터를 프로메테우스로 수집하고 싶다면 파이썬이나 Golang 등에서 제공하는 exporter 라이브러리를 통해 커스텀 exporter를 만들 수도 있습니다. 혹은 필요에 맞는 적절한 오픈소스 exporter를 가져다 쓸 수도 있으며, CAdvisor는 그러한 오픈소스 중 하나라고 볼 수 있습니다.

대부분의 오픈소스에서는 메트릭을 반환하기 위한 엔드포인트 경로로 /metrics를 기준으로 삼습니다. kubelet에서는 /metrics와 /metrics/cadvisor가 나뉘어서 존재합니다. /metrics는 kubelet 자체에 대한 애플리케이션 수준의 메트릭을, /metrics/cadvisor는 CAdvisor에서 반환하는 컨테이너 수준의 메트릭을 반환합니다.



모니터링 메트릭의 분류

모니터링 메트릭은 크게 3단계로 분류할 수 있습니다.

  • 인프라 수준의 메트릭: 호스트 레벨에서의 메트릭을 의미합니다. 예를 들어 호스트에서 사용 중인 파일 디스크립터의 개수, 호스트에 마운트돼 있는 디스크 사용량, 호스트 NIC의 패킷 전송량 등이 될 수 있습니다. 뒤에서 설명할 node-exporter라는 도구가 제공하는 메트릭은 인프라 수준에 해당합니다.
  • 컨테이너 수준의 메트릭: 컨테이너 레벨에서의 메트릭을 의미합니다. 예를 들어, 컨테이너별 CPU와 메모리 사용량, 컨테이너 프로세스의 상태, 컨테이너에 할당된 리소스 할당량, 쿠버네티스 포드의 상태 등이 포함될 수 있습니다. CAdvisor가 제공하는 메트릭은 컨테이너 수준에 해당합니다.
  • 애플리케이션 수준의 메트릭: 인프라와 컨테이너를 제외한, 애플리케이션 레벨에서 정의하는 모든 메트릭을 의마합니다. 마이크로서비스에서 발생하는 트레이싱(tracing) 데이터일 수도 있고, 애플리케이션 로직에 종속적인 데이터일 수도 있으며, 서버 프레임워크에서 제공하는 모니터링 데이터일 수도 있습니다.

실제로 CAdvisor가 제공하는 컨테이너 수준의 메트릭에 어떤 것이 있는지 살펴보겠습니다. CAdvisor 버전 확인

$ sudo docker run \
    --volume=/:/rootfs:ro \
    --volume=/var/run:/var/run:ro \
    --volume=/sys:/sys:ro \
    --volume=/var/lib/docker/:/var/lib/docker:ro \
    --volume=/dev/disk/:/dev/disk:ro \
    --publish=8080:8080 \
    --detach=true \
    --name=cadvisor \
    --privileged \
    --device=/dev/kmsg \
    gcr.io/cadvisor/cadvisor:v0.39.3 # 버전 확인 후 변경

$ curl localhost:8080/metrics

대부분 컨테이너에 관련된 메트릭이라는 것을 알 수 있습니다. 이러한 메트릭을 시계열 데이터베이스에 수집하고, 원하는 형태로 가공하면 컨테이너 수준의 모니터링을 할 수 있습니다.

이와 유사하게 인프라 수준에서의 메트릭을 제공하는 node-exporter라는 도구도 있으며, 애플리케이션 수준에서의 메트릭을 제공하는 프레임워크 또는 exporter 라이브러리도 있습니다.



쿠버네티스 모니터링 기초

metrics-server

쿠버네티스 메트릭을 수집해 사용할 수 있도록 몇 가지 add-on(쿠버네티스 내부에 설치해 추가적으로 기능을 활용할 수 있도록 제공하는 도구)을 제공합니다. 그 중 가장 기초적인 것은 컨테이너와 인프라 레벨에서의 메트릭을 수집하는 metrics-server라는 도구입니다. metrics-server를 설치하면 포드의 오토스케링링, 사용 중인 리소스 확인 등 여러 기능을 추가적으로 사용할 수 있습니다.

각 포드, 노드의 리소스 사용량을 확인하는 명령어로 kubectl top이라는 명령어가 있습니다. 단일 도커 호스트와는 달리 쿠버네티스는 여러 개의 노드로 구성되 있기 때문에 docker stats처럼 쉽게 메트릭을 확인할 수는 없습니다. kubectl top 명령어를 사용하려면 클러스터 내부의 메트릭을 모아서 제공하는 별도의 무언가가 필요한데 metrics-server가 바로 그 역할입니다.

$ wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
$ vi components.yaml

example

example

--kubelet-insecure-tls 옵션을 추가합니다. 그리고 nodes/stats 테스트를 위해 클러스터롤의 권한 정보에 url을 하나 더 추가합니다.

$ kubectl apply -f components.yaml

metrics-server는 기본적으로 kube-system 네임스페이스에 생성됩니다. metrics-server가 정상적으로 생성되면 이제 kubectl top 명령어를 사용할 수 있습니다.

$ kubectl get po -n kube-system | grep metrics-server
$ kubectl top po -n kube-system
$ kubectl top no


metrics-server 동작 원리: APIService 리소스

metrics-server가 어떤 방식으로 메트릭을 모아서 사용자에게 보여주는지 알아보겠습니다.

노드의 에이전트인 kubelet은 CAdvisor를 자체적으로 내장하고 있으며, 포드와 노드 메트릭을 반환하는 /stats/summary라는 엔드포인트를 제공합니다. kubelet은 기본적으로 노드의 10250 포트로 연결돼있습니다.

kubelet의 /stats/summary에 접근하기 위해서는 권한 정보가 필요합니다. /stats/summary에 접근하기 위한 권한 정보를 curl에 넣어주어 요청하면 메트릭을 확인할 수 있습니다. 즉, kubelet으로부터 메트릭을 가져오기 위한 권한을 ClusterRole로 정의해서 서비스 어카운트에 연결한 뒤, 서비스 어카운트의 토큰을 curl의 헤더에 포함시켜 요청해야 정상적인 메트릭을 확인할 수 있습니다. /nodes/stats라는 리소스에 접근할 수 있는 권한은 방금 components.yaml에 url을 추가하면서 부여했습니다.

# 본인의 metrics-server 이름으로
$ kubectl get secrets -n kube-system metrics-server-token-jg949 -o jsonpath={.data.token} | base64 -d
$ curl https://Master 노드 호스트 IP:10250/stats/summary -k -H "Authorization: Bearer 위에서 나온 토큰"

이런 방식으로 metrics-server는 kubelet으로부터 주기적으로 노드, 포드 메트릭을 수집합니다. 그리고 나서 metrics-server는 수집한 데이터를 한 번 더 정제해 외부에 제공하며, kubectl top 명령어는 metrics-server가 제공하는 메트릭을 통해 결과를 보여줍니다.

example

지금 확인해본 메트릭은 kubelet(CAdvisor)의 메트릭이고, metrics-server가 반환하는 메트릭을 확인해보겠습니다. 그러기 위해서 kube-system 네임 스페이스에 curl기능이 있는 ubuntu를 실행해서 요청을 해보면,

$ kubectl -n kube-system run -i --tty --rm debug --image=alicek106/ubuntu:curl --restart=Never -- bash
If you don't see a command prompt, try pressing enter.
root@debug:/# curl https://metrics-server:443 -k
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
  "reason": "Forbidden",
  "details": {},
  "code": 403
}

접근할 수 없다는 메세지가 나오는데 응답 형식이 json 형태로 API 서버가 응답한 것을 알 수 있습니다. 이렇게 나오는 이유는 metrics-server가 일종의 확장된 API 서버 역할을 하기 때문입니다.

API 서버의 스펙에 맞는 별도의 서버를 구축한 뒤, 이를 쿠버네티스에 등록하면 마치 확장된 API 서버처럼 기존의 kube api server와 합쳐져 확장되는 것입니다. 지금은 metrics-server가 쿠버네티스에 확장된 API 서버로서 등록돼 있으며, API 서버의 역할을 일부 담당하고 있습니다. metrics-server에 의해 확장된 API는 APIService라고 하는 리소스를 사용해 쿠버네티스에 등록할 수 있는데, 이 APIService 리소스는 이전에 metrics-server(components.yaml)을 배포할 때 생성됐습니다. components.yaml의 APIService쪽을 보면,

example

APIService 리소스는 새로운 API를 확장해 사용하기 위해서는 어떠한 서비스에 접근해야 하는지를 정의합니다. 새로 생성될 API의 이름은 metrics.k8s.io이고, 이 새로운 API는 metrics-server에 접근함으로써 사용할 수 있습니다. APIService를 생성한 뒤 metrics.k8s.io라는 이름의 API를 호출하게 되면 이는 쿠버네티스의 API 서버인 kube-apiserver에서 처리하지 않고, 확장된 API 서버인 metrics-server에서 처리하게 됩니다.

이런 API 확장 방식을 쿠버네티스에서 API Aggregation이라고 합니다. API Aggregation이라는 단어를 그대로 해석한 것처럼 추가적인 API를 묶어서 마치 쿠버네티스 API처럼 사용할 수 있는 것입니다.

example

  1. APIService 리소스를 통해 metrics-server를 확장된 API 서버로 등록합니다.
  2. 사용자는 쿠버네티스 API 서버에 metrics.k8s.io API 요청을 전송합니다.
  3. 해당 API는 API Aggregation에 의해 metrics-server로부터 제공되고 있으므로 쿠버네티스 API 서버는 해당 요청을 metrics-server에 전달합니다.
  4. 사용자는 metrics-server가 처리한 API 응답을 반환받습니다. 위 경우에는 metrics-server가 /stats/summary로부터 수집한 노드, 포드의 리소스 사용량 메트릭을 반환받았습니다.

kubectl에 --raw 옵션을 추가하면 쿠버네티스 API 서버(kube-apiserver)에 직접 API를 요청하는 것처럼 확인 해볼 수 있습니다.

$ kubectl get --raw /apis/metrics.k8s.io | jq

nodes, pods를 명시하여 API를 호출하면 kubectl top 명령어에서 사용되는 메트릭을 확인할 수 있습니다.

$ kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes | jq
$ kubectl get --raw /apis/metrics.k8s.io/v1beta1/pods | jq


kube-state-metrics

kube-state-metrics는 쿠버네티스 리소스의 상태에 관련된 메트릭을 제공하는 애드온입니다. 포드의 상태가 Running인지 또는 디플로이먼트의 레플리카 개수가 몇 개인지 등은 리소스 상태에 해당하며, kube-state-metrics애드온을 통해 확인할 수 있습니다.

$ git clone https://github.com/kubernetes/kube-state-metrics.git
$ cd kube-state-metrics/examples/standard
$ kubectl apply -f .

curl로 요청을 보내면 관련 메트릭을 확인해볼 수 있습니다.

$ kubectl run -i --tty --rm debug --image=alicek106/ubuntu:curl --restart=Never -- bash
If you don't see a command prompt, try pressing enter.
root@debug:/# curl kube-state-metrics.kube-system.svc:8080/metrics


node-exporter

node-exporter는 인프라 수준에서의 메트릭을 제공하는 exporter입니다. 컨테이너 메트릭에 초점을 맞춘 CAdvisor와는 달리 node-exporter는 파일 시스템, 네트워크 패킷 등과 같이 호스트 측면에서의 다양하고 자세한 메트릭을 제공합니다.

kube-prometheus의 깃허브 저장소에서 쿠버네티스용 node-exporter 매니페스트를 찾을 수 있습니다. kube-prometheus 깃허브 저장소에는 프로메티우스를 중심으로 하는 모니터링 시스템을 한번에 편하게 설치할 수 있도록 jsonnet 및 YAML 파일들을 제공합니다.

모니터링 시스템이 어떻게 구성되어 있는지 학습해보기 위해 책의 깃허브 저장소의 YAML 파일들로 구성해보겠습니다.

$ git clone https://github.com/alicek106/start-docker-kubernetes.git
$ cd start-docker-kubernetes/chapter14/node-exporter
$ kubectl apply -f .

node-exporter는 monitoring이라는 네임스페이스에 생성됐을 것입니다. node-exporter는 데몬셋으로 배포되어서 모든 노드에 포드가 하나씩 생성되어 있습니다.

$ kubectl get po -o wide -n monitoring

IP를 확인해보면 노드의 IP와 동일한 것을 알 수 있습니다. 이는 node-exporter가 호스트 네트워크 모드로 실행되기 때문입니다. 포드 스펙에 아래의 그림과 같이 hostNetwork를 설정해주면 마치 docker run 명령어의 --net host와 같은 효과를 낼 수 있습니다.

example

따라서 노드의 IP에 접근할 수 있으면 node-exporter에도 접근할 수 있습니다. node-exporter의 기본 포트인 9100으로 요청을 전송하면 다양한 메트릭을 확인할 수 있습니다.

$ curl {노드 IP}:9100/metrics

만약 필요 없는 메트릭이 있다면 node-exporter 데몬셋 YAML의 실행 인자 중 --no-collector를 적절히 추가하는 방식으로 수집하지 않는 방법도 있습니다.

지금까지 다뤘던 메트릭 수집 도구를 정리해보면,

  • kubelet에 내장돼 있는 CAdvisor: 특정 노드에 컨테이너 수준의 메트릭을 반환합니다. metrics-server는 kubelet의 / stats/summary에 접근해 포드와 리소스 관련 메트릭을 임시로 메모리에 수집하고, 이를 확장된 API로서 제공했습니다.
  • kube-state-metrics: 쿠버네티스 리소스의 상태에 관한 메트릭을 반환합니다. 별도의 인증 없이 kube-state-metrics 서버의 8080 포트와 /metrics 경로로 요청해서 메트릭을 확인할 수 있습니다.
  • node-exporter: 컨테이너가 아닌 인프라 수준에서의 메트릭을 반환합니다. 데몬셋의 형태로 모든 노드에 배포했으며, 9100 포트와 /metrics 경로로 요청해서 메트릭을 확인할 수 있습니다.



프로메테우스를 활용한 메트릭 수집

위쪽에서 설명한 메트릭 수집 도구들은 /metrics 같은 엔드포인트를 제공합니다. 프로메테우스를 설치한 뒤 메트릭을 수집할 수 있는 엔드포인트를 프로메테우스에 설정하기만 하면 메트릭이 자동적으로 수집될 것입니다.


프로메테우스 설치

프로메테우스를 설치하는 방법 중 직관적으로는 도커 이미지로 디플로이먼트를 배포하는 방법을 생각해 볼 수 있습니다. 하지만 이번 내용에서는 프로메테우스 오퍼레이터와 커스텀 리소스를 활용해 프로메테우스를 관리하는 방법을 사용할 것입니다.

example

prometheus라는 커스텀 리소스를 생성하면 실제로 프로메테우스 포드가 생성됩니다. 그뿐만 아니라 프로메테우스에서 메트릭을 수집할 대상이나 기타 설정 또한 커스텀 리소스로 정의해 사용할 수 있으며, 이로부터 생성된 프로메테우스 설정들은 프로메테우스에서 자동으로 리로드되어 적용됩니다.

프로메테우스 오퍼레이터는 깃허브 저장소에서 설치를 위한 YAML 파일을 제공합니다. 오퍼레이터 사용을 위한 여러 CRD(Custom Resource Definition)도 함께 생성됩니다.

$ git clone https://github.com/prometheus-operator/prometheus-operator.git
$ cd prometheus-operator/
$ kubectl create -f bundle.yaml 
# (apply는 오류뜸)
$ kubectl get po

prometheus라는 이름의 커스텀 리소스를 생성해 프로메테우스를 배포합니다. 다음 YAML 파일은 오브젝트의 종류(kind)가 Prometheus입니다.

$ cd start-docker-kubernetes/chapter14/
$ kubectl apply -f prometheus-simple.yaml
$ kubectl get po
$ kubectl get svc

이 YAML 파일을 사용해 Prometheus 리소스를 생성하면 프로메테우스 포드와 서비스가 함께 생성됩니다. 위쪽의 그림과 같이 오퍼레이터가 커스텀 리소스의 생성을 감지한 뒤 프로메테우스 포드를 생성하는 동작을 수행한 것입니다.

프로메테우스가 자체적으로 제공하는 웹 UI로 접속해 보겠습니다. prometheus-operated라는 이름의 서비스는 ClusterIP 타입이기 때문에 브라우저에서 직접 접근하는 것은 불가능합니다. kubectl port-forward 명령어를 사용하면 외부로 노출되지 않는 서비스에 임시로 접근할 수 있도록 로컬호스트에 포트 포워딩을 생성할 수 있습니다.

$ kubectl port-forward --address=0.0.0.0 svc/prometheus-operated 19090:9090
# 명령어를 실행한 마스터 노드의 호스트 IP 주소, 포트 19090으로 웹사이트 접속

example


프로메테우스로 메트릭 수집하기

프로메테우스가 exporter로부터 메트릭을 가져오려면 메트릭을 가져올 수 있는 엔드포인트를 프로메테우스에게 알려줄 필요가 있습니다. 만약 프로메테우스 오퍼레이터를 사용하지 않을 경우에는 프로메테우스 포드 내부에 존재하는 설정 파일에 엔드포인트를 직접 기입한 뒤 프로메테우스 프로세스를 리로드해야 겠지만 지금은 커스텀 리소스를 사용하고 있으므로 그러지 않아도 됩니다. ServiceMonitor라는 커스텀 리소스를 사용하면 어떠한 엔드포인트로부터 메트릭을 가져올 것인지를 쿠버네티스 리소스로 정의하고, 이를 프로메테우스에 자동으로 적용할 수 있기 때문입니다.

ServiceMonitor 리소스를 생성합니다.

$ cd start-docker-kubernetes/chapter14
$ kubectl apply -f node-exporter-serviceMonitor.yaml

example

ServiceMonitor에서의 라벨 셀렉터는 어떤 서비스를 선택할 것인지를 의미하며, 위에서 설정돼 있는 라벨은 기존에 만들어둔 node-exporter 서비스의 라벨입니다. node-exporter 서비스에는 앞서 생성해 둔 node-exporter 데몬셋 포드들이 연결돼 있을 것이므로 최종적으로 프로메테우스는 각 node-exporter 포드에 접근해 메트릭을 수집하게 됩니다.

시계열 데이터베이스가 메트릭을 수집하는 방법에는 Push 방식과 Pull 방식이 있습니다. Push는 exporter가 직접 데이터베이스로 메트릭을 전송(push)해서 저장하는 방식이고, Pull은 데이터베이스가 exporter에 접근해 메트릭을 당겨오는(pull) 방식입니다. 프로메테우스는 Pull 방식을 사용합니다.

ServiceMonitor를 생성하면 프로메테우스의 설정에 잘 반영됐는지 확인해볼 수 있습니다. Status → Configuration을 클릭하면 프로메티우스에서 현재 사용 중인 설정 파일(prometheus.yml)을 볼 수 있습니다.

example

이젠 프로메테우스가 실제로 node-exporter를 메트릭 수집 대상으로서 사용하고 있는지 확인해야 하는데 상단 메뉴에서 Status → Targets를 클릭합니다.

example

타켓이 잡히지 않아 포드의 로그를 확인하면,

$ kubectl logs -f prometheus-prometheus-0 -c prometheus --tail 10

example

default 서비스 어카운트가 pods, service, endpoints 등의 리소스를 list할 수 없는 권한 문제임을 알 수 있습니다. Prometheus 커스텀 리소스를 생성할 때 서비스 어카운트도 별도로 설정해주지 않았고, 권한도 특별하게 설정한 것도 없었습니다.

Prometheus라는 이름의 서비스 어카운트를 생성하고 적절한 권한을 부여한 뒤, 프로메테우스 포드가 이 서비스 어카운트를 사용하도록 설정합니다.

$ cd start-docker-kubernetes/chapter14

# 클러스터롤
$ kubectl apply -f prometheus-clusterRole.yaml

# 롤바인딩
$ kubectl apply -f prometheus-clusterRoleBinding.yaml

# 서비스 어카운트
$ kubectl apply -f prometheus-serviceAccount.yaml

# pod 재생성
$ kubectl apply -f prometheus-sa-configured.yaml

port forwarding을 다시 해준 뒤 프로메테우스 웹 UI에서 Targets를 다시 확인해보면 node-exporter 포드가 제대로 인식돼 있을 것입니다. 프로메테우스는 이러한 Targets에게 각각 접근해 메트릭을 수집해 저장합니다.

example

그리고 상단의 Graph를 클릭해 메트릭의 종류를 확인해보면 node-exporter가 제공하는 메트릭이 존재합니다. node-exporter가 제공하는 메트릭은 인프라 수준에 해당하기 때문에 파일시스템, 디스크, 네트워크 등에 관련된 들을 볼 수 있습니다.

example

이런 방식으로 kubelet의 CAdvisor와 kube-state-metrics에 대해서도 메트릭을 수집할 수 있습니다. kubelet과 kube-state-metrics를 위한 ServiceMonitor 또한 생성해서 메트릭을 수집해보겠습니다.

$ cd start-docker-kubernetes/chapter14
$ kubectl apply -f kube-state-metrics-serviceMonitor.yaml
$ kubectl apply -f kubelet-serviceMonitor.yaml

example

example


그라파나로 프로메테우스 메트릭 시각화하기

프로메테우스에 메트릭이 잘 수집됐다면 다음은 메트릭을 보기 좋게 시각화 할 필요가 있습니다. 그라파나 대시보드 도구를 사용해 메트릭을 확인해보겠습니다.

$ cd start-docker-kubernetes/chapter14
$ kubectl apply -f grafana.yaml

# 다른 shell에서 
$ kubectl port-forward --address=0.0.0.0 svc/grafana 3000:3000
# 명령어를 실행한 노드(마스터노드) 호스트 IP로 접속

초기 계정인 admin / admin을 입력하고 들어갑니다.

example

그라파나에서 메트릭을 시각화하려면 먼저 프로메테우스를 데이터 소스로 등록한 뒤, 쿼리를 통해 메트릭을 시각화하는 대시보드를 생성해야 합니다.

example

설정 정보들을 입력합니다.

example

이 데이터 소스를 이용해 그라파나 대시보드를 생성합니다. 그라파나 공식 사이트에 접속해서 대시보드 템플릿을 가져올 수 있습니다. 이 책의 저자분이 만드신 대시보드의 ID 13077을 사용해서 대시보드를 구성합니다.

example

example

example





출처
시작하세요! 도커/쿠버네티스(용찬호 저, 위키북스)
example

728x90
반응형
댓글
반응형
250x250
글 보관함
최근에 달린 댓글
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Total
Today
Yesterday
링크