본문 바로가기

Cloud/Kubernetes

[metallb] prometheus 수집 값 보기

 PaaS 플랫폼에서 로드밸런서 서비스를 지원하기 위해 metallb를 사용하고 있다. metallb를 사용하지 않으면 노드포트 혹은 클러스터 아이피로밖에 사용하지 못한다. 각각 클러스터 아이피는 내부 통신만 가능하고, 노드 포트는 보안적인 면에서 좋은 방법이 아니다. layer 2 모드밖에 사용해보지 못했지만 어느 정도 써봤고 모니터링이 필요한 부분이 있어 해당 포스팅을 작성하게 되었다.

 버전은 kube 1.17.6, metallb 0.8.2 기준이다.


1. prometheus 옵션

 metallb pod는 metallb-controller pod(deployment)와 speaker(daemonset) pod로 구분된다. 각각의 yaml을 보면 prometheus scrape 옵션이 있다. 7472 포트를 통해 접근하며 이를 통해 메트릭 조회가 가능하다.

 

컨트롤러와 스피커가 각각 옵션을 가지고 있는 것을 볼 수 있다.

2. target 확인

 설정에 따라 다르겠지만 기본 설치를 진행한 경우 monitoring/kubernetes-pods/의 target으로 잡혀있다. speaker의 경우 daemonset이기 때문에 node ip를 통해 메트릭을 조회할 수 있고 controller는 pod ip를 통해 메트릭을 조회할 수 있다. 

3. 수집 데이터 확인

 Controller와 Speaker의 수집값도 약간의 차이가 있다. 기본 메트릭 이외에 metallb와 관련된 메트릭이 존재한다.

- Controller

# HELP metallb_allocator_addresses_in_use_total Number of IP addresses in use, per pool
# TYPE metallb_allocator_addresses_in_use_total gauge

# HELP metallb_k8s_client_config_loaded_bool 1 if the MetalLB configuration was successfully loaded at least once.
# TYPE metallb_k8s_client_config_loaded_bool gauge

# HELP metallb_k8s_client_config_stale_bool 1 if running on a stale configuration, because the latest config failed to load.
# TYPE metallb_k8s_client_config_stale_bool gauge

# HELP metallb_k8s_client_update_errors_total Number of k8s object updates that failed for some reason.
# TYPE metallb_k8s_client_update_errors_total counter

# HELP metallb_k8s_client_updates_total Number of k8s object updates that have been processed.
# TYPE metallb_k8s_client_updates_total counter

- Speaker

# HELP metallb_k8s_client_config_loaded_bool 1 if the MetalLB configuration was successfully loaded at least once.
# TYPE metallb_k8s_client_config_loaded_bool gauge

# HELP metallb_k8s_client_config_stale_bool 1 if running on a stale configuration, because the latest config failed to load.
# TYPE metallb_k8s_client_config_stale_bool gauge

# HELP metallb_k8s_client_update_errors_total Number of k8s object updates that failed for some reason.
# TYPE metallb_k8s_client_update_errors_total counter

# HELP metallb_k8s_client_updates_total Number of k8s object updates that have been processed.
# TYPE metallb_k8s_client_updates_total counter

# HELP metallb_layer2_gratuitous_sent Number of gratuitous layer2 packets sent for owned IPs as a result of failovers
# TYPE metallb_layer2_gratuitous_sent counter

# HELP metallb_layer2_requests_received Number of layer2 requests received for owned IPs
# TYPE metallb_layer2_requests_received counter

# HELP metallb_layer2_responses_sent Number of layer2 responses sent for owned IPs in response to requests
# TYPE metallb_layer2_responses_sent counter

# HELP metallb_speaker_announced Services being announced from this node. This is desired state, it does not guarantee that the routing protocols have converged.
# TYPE metallb_speaker_announced gauge

 지정한 풀 안에서 사용 중인 개수가 궁금했으므로, controller의 메트릭을 보면 되었다.

 의심충이라서 실제로 값이 맞는지 확인해본다.

[root@master metallb]# kubectl get svc -A | grep LoadBalancer | wc
     68     476   25501

 

4. Grafana를 통해 그래프 생성

 여기부터 머리아프기 시작했는데, 총 개수는 주지 않았기 때문이다. 찾아보면 "metallb_allocator_addresses_total" 이라는 메트릭을 제공하는 것으로 보이는데 버전 0.9.2에서부터 제공한다. 고로 나는 못해봄 ㅎ

그래서 그냥 꿩대신 닭으로 (그러면 안되지만) 절대값 넣어서 계산해주었다. 어쩔 수 없지... 값을 안주는걸 어떡해

{
  "datasource": "prometheus",
  "aliasColors": {},
  "breakPoint": "75%",
  "cacheTimeout": null,
  "combine": {
    "label": "Others",
    "threshold": 0
  },
  "fontSize": "100%",
  "format": "short",
  "gridPos": {
    "h": 6,
    "w": 4,
    "x": 0,
    "y": 7
  },
  "id": 45,
  "interval": null,
  "legend": {
    "percentage": true,
    "show": true,
    "sideWidth": 150,
    "values": true
  },
  "legendType": "On graph",
  "links": [],
  "nullPointMode": "connected",
  "options": {},
  "pieType": "pie",
  "strokeWidth": 1,
  "targets": [
    {
      "expr": "metallb_allocator_addresses_in_use_total",
      "legendFormat": "Usage",
      "refId": "A"
    },
    {
      "expr": "[개수] - metallb_allocator_addresses_in_use_total",
      "legendFormat": "Unusage",
      "refId": "B"
    }
  ],
  "timeFrom": null,
  "timeShift": null,
  "title": "Loadbalancer usage",
  "type": "grafana-piechart-panel",
  "valueName": "current"
}

LoadBalancer List도 만들었다. 주의할 점은 실제로 pod와 연결되지 않은 LoadBalancer는 조회되지 않는 점인데 kube-service metrics하고 비교해서 사용 여부를 표시하려고 했는데 걔네들은 loadbalancer ip를 가지고 있지 않아서 ㅠㅠ 매핑 할 값이 없다. 이름도 서로 다르게 들어가니... 이건 조금 더 연구해봐야할듯

{
  "datasource": "prometheus",
  "columns": [],
  "description": "SVC는 생성되어 있으나, 연결 된 Pod가 없을 경우 목록에 나타나지 않습니다.",
  "fontSize": "100%",
  "gridPos": {
    "h": 6,
    "w": 20,
    "x": 4,
    "y": 7
  },
  "id": 47,
  "options": {},
  "pageSize": null,
  "showHeader": true,
  "sort": {
    "col": 7,
    "desc": false
  },
  "styles": [
    {
      "alias": "Time",
      "dateFormat": "YYYY-MM-DD HH:mm:ss",
      "pattern": "Time",
      "type": "hidden"
    },
    {
      "alias": "LoadBalancer",
      "colorMode": null,
      "colors": [
        "rgba(245, 54, 54, 0.9)",
        "rgba(237, 129, 40, 0.89)",
        "rgba(50, 172, 45, 0.97)"
      ],
      "dateFormat": "YYYY-MM-DD HH:mm:ss",
      "decimals": 2,
      "mappingType": 1,
      "pattern": "ip",
      "thresholds": [],
      "type": "number",
      "unit": "short"
    },
    {
      "alias": "Service",
      "colorMode": null,
      "colors": [
        "rgba(245, 54, 54, 0.9)",
        "rgba(237, 129, 40, 0.89)",
        "rgba(50, 172, 45, 0.97)"
      ],
      "dateFormat": "YYYY-MM-DD HH:mm:ss",
      "decimals": 2,
      "mappingType": 1,
      "pattern": "service",
      "preserveFormat": false,
      "sanitize": false,
      "thresholds": [],
      "type": "string",
      "unit": "short"
    },
    {
      "alias": "Node",
      "colorMode": null,
      "colors": [
        "rgba(245, 54, 54, 0.9)",
        "rgba(237, 129, 40, 0.89)",
        "rgba(50, 172, 45, 0.97)"
      ],
      "dateFormat": "YYYY-MM-DD HH:mm:ss",
      "decimals": 2,
      "mappingType": 1,
      "pattern": "node",
      "thresholds": [],
      "type": "string",
      "unit": "short"
    },
    {
      "alias": "",
      "colorMode": null,
      "colors": [
        "rgba(245, 54, 54, 0.9)",
        "rgba(237, 129, 40, 0.89)",
        "rgba(50, 172, 45, 0.97)"
      ],
      "decimals": 2,
      "pattern": "/.*/",
      "thresholds": [],
      "type": "hidden",
      "unit": "short"
    }
  ],
  "targets": [
    {
      "expr": "metallb_speaker_announced",
      "format": "table",
      "instant": true,
      "refId": "A"
    },
    {
      "refId": "B"
    }
  ],
  "timeFrom": null,
  "timeShift": null,
  "title": "LoadBalancer List",
  "transform": "table",
  "type": "table"
}

찾아서 수정했다.

{
  "datasource": "prometheus",
  "columns": [],
  "description": "Bind가 -인 SVC는 실제로 할당되지 않은 Service 입니다.",
  "fontSize": "100%",
  "gridPos": {
    "h": 6,
    "w": 20,
    "x": 4,
    "y": 7
  },
  "id": 48,
  "options": {},
  "pageSize": null,
  "showHeader": true,
  "sort": {
    "col": 7,
    "desc": false
  },
  "styles": [
    {
      "alias": "Time",
      "dateFormat": "YYYY-MM-DD HH:mm:ss",
      "pattern": "Time",
      "type": "hidden"
    },
    {
      "unit": "short",
      "type": "number",
      "alias": "IP",
      "decimals": 2,
      "colors": [
        "rgba(245, 54, 54, 0.9)",
        "rgba(237, 129, 40, 0.89)",
        "rgba(50, 172, 45, 0.97)"
      ],
      "colorMode": null,
      "pattern": "ip",
      "dateFormat": "YYYY-MM-DD HH:mm:ss",
      "thresholds": [],
      "mappingType": 1
    },
    {
      "unit": "short",
      "type": "string",
      "alias": "Namespace",
      "decimals": 2,
      "colors": [
        "rgba(245, 54, 54, 0.9)",
        "rgba(237, 129, 40, 0.89)",
        "rgba(50, 172, 45, 0.97)"
      ],
      "colorMode": null,
      "pattern": "namespace",
      "dateFormat": "YYYY-MM-DD HH:mm:ss",
      "thresholds": [],
      "mappingType": 1
    },
    {
      "unit": "short",
      "type": "string",
      "alias": "Service",
      "decimals": 2,
      "colors": [
        "rgba(245, 54, 54, 0.9)",
        "rgba(237, 129, 40, 0.89)",
        "rgba(50, 172, 45, 0.97)"
      ],
      "colorMode": null,
      "pattern": "service",
      "dateFormat": "YYYY-MM-DD HH:mm:ss",
      "thresholds": [],
      "mappingType": 1
    },
    {
      "unit": "short",
      "type": "number",
      "alias": "Bind",
      "decimals": 0,
      "colors": [
        "rgba(245, 54, 54, 0.9)",
        "rgba(237, 129, 40, 0.89)",
        "rgba(50, 172, 45, 0.97)"
      ],
      "colorMode": "cell",
      "pattern": "Value #B",
      "dateFormat": "YYYY-MM-DD HH:mm:ss",
      "thresholds": [
        "0",
        "1"
      ],
      "mappingType": 1,
      "preserveFormat": false
    },
    {
      "alias": "",
      "colorMode": null,
      "colors": [
        "rgba(245, 54, 54, 0.9)",
        "rgba(237, 129, 40, 0.89)",
        "rgba(50, 172, 45, 0.97)"
      ],
      "decimals": 2,
      "pattern": "/.*/",
      "thresholds": [],
      "type": "hidden",
      "unit": "short"
    }
  ],
  "targets": [
    {
      "expr": "kube_service_status_load_balancer_ingress",
      "format": "table",
      "instant": true,
      "refId": "A"
    },
    {
      "refId": "B",
      "expr": "sum (metallb_speaker_announced) by (ip)",
      "instant": true,
      "format": "table"
    }
  ],
  "timeFrom": null,
  "timeShift": null,
  "title": "LoadBalancer List",
  "transform": "table",
  "type": "table"
}