[![logo](https://www.hongsnet.net/images/logo.gif)](https://www.hongsnet.net)

# 개요

`K8s` 환경에서 모니터링시스템을 구축한다.

> 구성요소 : Prometheus + cAdvisor + Grafana + AlertManager

## System Overview

- CentOS 7 (3.10.0-957.el7.x86_64)
- K8s

```bash
# kubectl version
Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.4", GitCommit:"e87da0bd6e03ec3fea7933c4b5263d151aafd07c", GitTreeState:"clean", BuildDate:"2021-02-18T16:12:00Z", GoVersion:"go1.15.8", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.4", GitCommit:"e87da0bd6e03ec3fea7933c4b5263d151aafd07c", GitTreeState:"clean", BuildDate:"2021-02-18T16:03:00Z", GoVersion:"go1.15.8", Compiler:"gc", Platform:"linux/amd64"}
```

```bash
# kubectl get nodes
NAME     STATUS   ROLES                  AGE   VERSION
cube01   Ready    control-plane,master   12d   v1.20.4
cube02   Ready    <none>                 12d   v1.20.4
cube03   Ready    <none>                 12d   v1.20.4
cube04   Ready    <none>                 12d   v1.20.4
```

## K8s에 모니터링시스템을 구성하는 방법

- Prometheus Operator
- Helm Chart를 이용한 Package Install
- `Manual`

> 특히 Operator는 정말 간단하게 구성할 수 있으나, K8s에 좀 더 가까워지기 위해 **Manual**로 진행한다. 참고적으로 Manual 구성도 그리 복잡하진 않다.


# Overview

* [ **STEP 1** ] : namespace 생성
* [ **STEP 2** ] : PV,PVC 생성
* [ **STEP 3** ] : Cluster Role 생성
* [ **STEP 4** ] : Prometheus configmap 설정 및 생성
* [ **STEP 5** ] : Prometheus Pod Deployment, Prometheus node-exporter, Prometheus Service 생성 및 배포
> Prometheus node-exporter는 node-exporter와 다르다. **kube-system** namespace에 리소스현황을 제공한다. 따라서 아래에서 각 `Node`에 추가적으로 node-exporter를 설치할 것이다.
* [ **STEP 6** ] : Kube State Metrics 배포
* [ **STEP 7** ] : Grafana 연동 및 DataSource 추가
* [ **STEP 8** ] : AlertManager 배포
* [ **STEP 9** ] : 각 Node에 node-exporter를 설치


> **kubectl** 명령으로 배포 시 **apply**|**create** 인자가 존재하는데, 일반적으로 **최초 실행시**에는 create로 실행하는 것이 원칙이고, 그 이후에는 apply로 인자를 주면 된다.


## namespace 생성

다음과 같이 monitoring이라는 네임스페이스를 생성한다.

```bash
# kubectl create ns monitoring
```

## PV,PVC 생성

공통적으로 아래의 Pod를 생성하면, 모두 메모리에 데이터가 위치하게 된다. 따라서 재시작 시 데이터가 모두 초기화되므로, 다음과 같이 영구볼륨(Persistent Volume)을 생성하여, 이를 디스크에 저장하도록 한다.

### Prometheus의 PV,PVC의 설정을 진행

```bash
# cat prometheus-data.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: prometheus-pv
  namespace: monitoring
  labels:
    type: local
    app: prometheus
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  hostPath:
    path: /MONITOR/PROMETHEUS
    type: DirectoryOrCreate
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - cube02

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: prometheus-pvc
  namespace: monitoring
  labels:
    type: local
    app: prometheus
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 10Gi
  selector:
    matchLabels:
      app: prometheus
      type: local
```

### Grafana의 PV, PVC의 설정을 진행

```bash
# cat grafana-data.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: grafana-pv
  namespace: monitoring
  labels:
    type: local
    app: grafana
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  hostPath:
    path: /MONITOR/GRAFANA
    type: DirectoryOrCreate
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - cube02

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: grafana-pvc
  namespace: monitoring
  labels:
    type: local
    app: grafana
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 10Gi
  selector:
    matchLabels:
      app: grafana
      type: local
```

### AlertManager의 PV, PVC의 설정을 진행

```bash
# cat alertmanager-data.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: alertmanager-pv
  namespace: monitoring
  labels:
    type: local
    app: alertmanager
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  hostPath:
    path: /MONITOR/ALERTMANAGER
    type: DirectoryOrCreate
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - cube02

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: alertmanager-pvc
  namespace: monitoring
  labels:
    type: local
    app: alertmanager
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 10Gi
  selector:
    matchLabels:
      app: alertmanager
      type: local
```

다음과 같이 스크립트를 이용하여, 세 가지 서비스에 대한 PV,PVC를 생성한다.

```bash
# cat data-pv_pvc_create.sh
#!/bin/bash

kubectl create -f promethes-data.yaml
kubectl create -f grafana-data.yaml
kubectl create -f alertmanager-data.yaml
```

만약 삭제하려면, 다음과 같이 진행한다.

```bash
# cat data-pv_pvc_remove.sh
#!/bin/bash

kubectl delete -f promethes-data.yaml
kubectl delete -f grafana-data.yaml
kubectl delete -f alertmanager-data.yaml
```

구성된 PV,PVC 정보는 다음과 같다.

```bash
# kubectl get pv
NAME                         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                    STORAGECLASS   REASON   AGE
prometheus-config-pv         1Gi        RWO            Retain           Bound    monitoring/prometheus-config-pvc         manual                  23h
alertmanager-pv              10Gi       RWO            Retain           Bound    monitoring/alertmanager-pvc              manual                  5d20h
grafana-pv                   10Gi       RWO            Retain           Bound    monitoring/grafana-pvc                   manual                  5d21h
prometheus-pv                10Gi       RWO            Retain           Bound    monitoring/prometheus-pvc                manual                  5d21h
```

## Cluster Role 생성 (**최초만 수행**)

다음 과정은 Prometheus가 K8s API에 접근할 수 있는 권한을 부여하는 과정이다. 결과적으로 ClusterRole은 monitoring namespace의 서비스 계정에 대한 권한을 부여하는 것이다.

```bash
# cat prometheus-cluster-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
  namespace: monitoring
rules:
- apiGroups: [""]
  resources:
  - nodes
  - nodes/proxy
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups:
  - extensions
  resources:
  - ingresses
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: default
  namespace: monitoring
```

다음과 같이 생성한다.

```bash
# kubectl create -f prometheus-cluster-role.yaml
```

## Prometheus configmap 설정 및 생성

주요 핵심적인 설정파일은 다음과 같이 두 가지가 존재한다.

- prometheus.yml
  - Prometheus의 Core 설정파일이다.
- prometheus.rules
  - 수집된 Metric에 대한 조건을 부여하여, 해당되면 AlertManager로 Alert을 발송할 수 있는 내역을 기입하는 설정파일 이다.

> 설정내역이 방대하기 때문에 현재 경로의 **prometheus-config-map.yaml**을 참조한다.

다음과 같이 생성한다.

```bash
# kubectl create -f prometheus-config-map.yaml
```

## Prometheus Pod Deployment, Prometheus node-exporter, Prometheus Service 생성 및 배포

### Prometheus Pod Deployment 배포

Prometheus POD의 **Deployment Object**를 생성한다.

```bash
# cat prometheus-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus-deployment
  namespace: monitoring
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus-server
  template:
    metadata:
      labels:
        app: prometheus-server
    spec:
      containers:
        - name: prometheus
          image: prom/prometheus:latest
          args:
            - "--config.file=/etc/prometheus/prometheus.yml"
            - "--storage.tsdb.path=/prometheus/"
            - "--web.enable-lifecycle"
          ports:
            - containerPort: 9090
          volumeMounts:
            - name: prometheus-config-volume
              mountPath: /etc/prometheus/
            - name: prometheus-storage-volume
              mountPath: /prometheus/
      nodeSelector:
        kubernetes.io/hostname: cube02
      volumes:
        - name: prometheus-config-volume
          configMap:
            defaultMode: 420
            name: prometheus-server-conf
        - name: prometheus-storage-volume
          persistentVolumeClaim:
            claimName: prometheus-pvc
```

> 생성은 아래의 스크립트에서 수행할 것이다.


### Prometheus node-exporter 배포

K8s의 node-exporter를 구성한다. 단, 여기서는 각 Node에 하나씩만 구성될 수 있도록 `DaemonSet` Object로 구성한다. 

```bash
# cat prometheus-node-exporter.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitoring
  labels:
    k8s-app: node-exporter
spec:
  selector:
    matchLabels:
      k8s-app: node-exporter
  template:
    metadata:
      labels:
        k8s-app: node-exporter
    spec:
      containers:
      - image: prom/node-exporter
        name: node-exporter
        ports:
        - containerPort: 9100
          protocol: TCP
          name: http
---
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: node-exporter
  name: node-exporter
  namespace: kube-system
spec:
  ports:
  - name: http
    port: 9100
    nodePort: 31672
    protocol: TCP
  type: NodePort
  selector:
    k8s-app: node-exporter

```

> 생성은 아래의 스크립트에서 수행할 것이다.


### Prometheus Service 생성 및 배포

서비스의 노출(Expose)는 **NodePort**를 사용한다.

```bash
# cat prometheus-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: prometheus-service
  namespace: monitoring
  annotations:
      prometheus.io/scrape: 'true'
      prometheus.io/port:   '9090'
spec:
  selector:
    app: prometheus-server
  type: NodePort
  ports:
    - port: 8080
      targetPort: 9090
      nodePort: 30003
```

### Start | Stop Script의 생성

아래의 스크립트는 특별한 것이 아니며, 시작|중지를 좀 더 간편하게 하기 위한 것이다.

- **Start Script**

```bash
# cat start-prometheus.sh
#!/bin/bash

kubectl apply -f prometheus-config-map.yaml
kubectl create configmap prometheus-server-conf --from-file prometheus-config-map.yaml
kubectl apply -f prometheus-deployment.yaml
kubectl apply -f prometheus-node-exporter.yaml
kubectl apply -f prometheus-svc.yaml
```

- Stop Script

```bash
# cat stop-prometheus.sh
#!/bin/bash

kubectl delete -f prometheus-svc.yaml
kubectl delete -f prometheus-node-exporter.yaml
kubectl delete -f prometheus-deployment.yaml
kubectl delete -f prometheus-config-map.yaml
kubectl delete configmap prometheus-server-conf
```

Start 스크립트 실행 후 현황은 다음과 같다.

```bash
# kubectl -n monitoring get po -o wide
NAME                                     READY   STATUS    RESTARTS   AGE     IP             NODE     NOMINATED NODE   READINESS GATES
node-exporter-8ggc9                      1/1     Running   0          8h      10.244.1.184   cube02   <none>           <none>
node-exporter-hlpcp                      1/1     Running   0          8h      10.244.2.191   cube03   <none>           <none>
node-exporter-ph4bs                      1/1     Running   0          8h      10.244.3.219   cube04   <none>           <none>
prometheus-deployment-544d8d78b9-qp2rf   1/1     Running   0          8h      10.244.1.183   cube02   <none>           <none>
```

또한 configmap의 현황은 다음과 같다.

```bash
# kubectl get configmap
NAME                     DATA   AGE
kube-root-ca.crt         1      12d
prometheus-server-conf   1      8h
```

## Kube State Metrics 배포

> `kube-state-metric`은 Pod에 대한 Resource Metric을 생성하는 타켓이다. 여기서 중요한 부분은 K8s의 Auto-Scaling에서 사용하는 `metric-server`와 전혀 다르다는 것이다. 즉, metric-server는 **HPA,VPA**에 사용되는 서비스이다. 

구성되는 파일내역은 다음과 같다.

- kube-state-cluster-role.yaml
- kube-state-deployment.yaml
- kube-state-svcaccount.yaml
- kube-state-svc.yaml

### Start | Stop Script의 생성

아래의 스크립트는 특별한 것이 아니며, 시작|중지를 좀 더 간편하게 하기 위한 것이다.

- **Start Script**

```bash
# cat start-kube-state.sh
#!/bin/bash

kubectl apply -f kube-state-cluster-role.yaml
kubectl apply -f kube-state-deployment.yaml
kubectl apply -f kube-state-svcaccount.yaml
kubectl apply -f kube-state-svc.yaml
```

> 상기 파일의 설정내역은 현재 경로의 파일을 참조한다.

- **Stop Script**

```bash
# cat stop-kube-state.sh
#!/bin/bash

kubectl apply -f kube-state-cluster-role.yaml
kubectl apply -f kube-state-deployment.yaml
kubectl apply -f kube-state-svcaccount.yaml
kubectl apply -f kube-state-svc.yaml
```

위의 Start 스크립트 실행 후 현황은 다음과 같다.

```bash
# kubectl get pod -n kube-system |grep kube-state
kube-state-metrics-5c544bc55-sdzkq                   1/1     Running   0          5d20h
```

## Grafana 연동 및 DataSource 추가

Promethues는 K8s의 Metric을 수집하는 시스템이다. 기본적으로 그래프를 제공하지만, 다양한 그래프 Type과 대시보드와 같은 전문적인 솔루션이 아니기 때문에 `Grafana`를 이용하여, 이를 시각화한다.

다음과 같이 Pod의 Deployment와 Service Object를 생성한다.

```bash
# cat grafana.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: grafana
  namespace: monitoring
spec:
  replicas: 1
  selector:
    matchLabels:
      app: grafana
  template:
    metadata:
      name: grafana
      labels:
        app: grafana
    spec:
      containers:
      - name: grafana
        image: grafana/grafana:latest
        ports:
        - name: grafana
          containerPort: 3000
        volumeMounts:
          - name: grafana-storage-volume
            mountPath: /var/lib/grafana
      nodeSelector:
        kubernetes.io/hostname: cube02
      volumes:
        - name: grafana-storage-volume
          persistentVolumeClaim:
            claimName: grafana-pvc
      securityContext:
        runAsUser: 0

---
apiVersion: v1
kind: Service
metadata:
  name: grafana
  namespace: monitoring
  annotations:
      prometheus.io/scrape: 'true'
      prometheus.io/port:   '3000'
spec:
  selector:
    app: grafana
  type: NodePort
  ports:
    - port: 3000
      targetPort: 3000
      nodePort: 30004
```

다음과 같이 실행한다.

```bash
# kubectl create -f grafana.yaml
```

실행 후 현황은 다음과 같다.

```bash
# kubectl get pod -n monitoring
NAME                                     READY   STATUS    RESTARTS   AGE
grafana-584c994b47-7bltv                 1/1     Running   0          5d19h
node-exporter-8ggc9                      1/1     Running   0          8h
node-exporter-hlpcp                      1/1     Running   0          8h
node-exporter-ph4bs                      1/1     Running   0          8h
prometheus-deployment-544d8d78b9-qp2rf   1/1     Running   0          8h
```

또한 서비스의 현황은 다음과 같다.

```bash
# kubectl get service -n monitoring
NAME                 TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
grafana              NodePort   10.103.8.163     <none>        3000:30004/TCP   5d19h
prometheus-service   NodePort   10.100.176.157   <none>        8080:30003/TCP   8h
```

> 접속 : 주소:**30004**

> Demo URL : https://grafana-k8s-demo.hongsnet.net <- 로그인 정보는 포트폴리오 참조

> Configuration -> DataSource

![grafana_datasource](./images/grafana-datasource.png)

> Save & Test 버튼을 클릭한 후 "**녹색 바탕**의 Data source is working" 결과가 나와야 한다.


## AlertManager 배포

AlertManager는 Promethues의 Rule에 대한 조건이 만족하면, Web-Hook 또는 Email 등으로 Alert을 실질적으로 수행하는 서비스다.

설정파일의 구성은 다음과 같다.

- alertmanager-configmap.yaml
- alert-template-configmap.yaml
> 참조 : https://twofootdog.tistory.com/17
- alertmanager.yaml
- alertmanager-svc.yaml

위 네 개의 설정파일에 대한 내역은 현재 경로의 파일들을 참조하고, 아래는 이 중 Mattermost로 Web-Hook을 발송하는 configmap에 대한 내역이다.

```bash
# cat alertmanager-configmap.yaml
kind: ConfigMap
apiVersion: v1
metadata:
  name: alertmanager-config
  namespace: monitoring
data:
  config.yml: |-
    global:
      #resolve_timeout: 1m
      slack_api_url: 'https://chat.hongsnet.net/hooks/XXXXXXXXX'

    route:
      receiver: 'slack-notifications'
      repeat_interval: 5m
      group_wait: 10s
      group_interval: 1m

    receivers:
    - name: 'slack-notifications'
      slack_configs:
       - channel: '#grafana'
         send_resolved: true
         icon_url: https://avatars3.githubusercontent.com/u/3380462
         title: |-
          [{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }} for {{ .CommonLabels.job }}
          {{- if gt (len .CommonLabels) (len .GroupLabels) -}}
            {{" "}}(
            {{- with .CommonLabels.Remove .GroupLabels.Names }}
              {{- range $index, $label := .SortedPairs -}}
                {{ if $index }}, {{ end }}
                {{- $label.Name }}="{{ $label.Value -}}"
              {{- end }}
            {{- end -}}
            )
          {{- end }}
         text: >-
           #{{ range .Alerts -}}
           *Alert:* {{ .Annotations.title }}{{ if .Labels.severity }} - `{{ .Labels.severity }}`{{ end }}

           *Description:* {{ .Annotations.description }}

           *Details:*
             {{ range .Labels.SortedPairs }} • *{{ .Name }}:* `{{ .Value }}`
             {{ end }}
           {{ end }}
```

> https://chat.hongsnet.net/hooks/XXXXXXXXX 의 grafana 채널에 Alert을 발송한다.


### Start | Stop Script의 생성

아래의 스크립트는 특별한 것이 아니며, 시작|중지를 좀 더 간편하게 하기 위한 것이다.

- **Start Script**

```bash
# cat start-alertmanager.sh
#!/bin/bash

kubectl apply -f alertmanager-configmap.yaml
kubectl apply -f alert-template-configmap.yaml
kubectl apply -f alertmanager.yaml
kubectl apply -f alertmanager-svc.yaml
```

- **Stop Script**

```bash
# cat stop-alertmanager.sh
#!/bin/bash

kubectl delete -f alertmanager-configmap.yaml
kubectl delete -f alert-template-configmap.yaml
kubectl delete -f alertmanager.yaml
kubectl delete -f alertmanager-svc.yaml
```

실행 후 현황은 다음과 같다.

```bash
# kubectl -n monitoring get po -o wide
NAME                                     READY   STATUS    RESTARTS   AGE     IP             NODE     NOMINATED NODE   READINESS GATES
alertmanager-65f5c498ff-q27wj            1/1     Running   0          14h     10.244.1.90    cube02   <none>           <none>
grafana-584c994b47-7bltv                 1/1     Running   0          5d20h   10.244.1.199   cube02   <none>           <none>
node-exporter-8ggc9                      1/1     Running   0          8h      10.244.1.184   cube02   <none>           <none>
node-exporter-hlpcp                      1/1     Running   0          8h      10.244.2.191   cube03   <none>           <none>
node-exporter-ph4bs                      1/1     Running   0          8h      10.244.3.219   cube04   <none>           <none>
prometheus-deployment-544d8d78b9-qp2rf   1/1     Running   0          8h      10.244.1.183   cube02   <none>           <none>
```

또한 서비스의 현황은 다음과 같다.

```bash
# kubectl get service -n monitoring
NAME                 TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
alertmanager         NodePort   10.110.183.32    <none>        9093:30005/TCP   14h
grafana              NodePort   10.103.8.163     <none>        3000:30004/TCP   5d20h
prometheus-service   NodePort   10.100.176.157   <none>        8080:30003/TCP   8h
```

## 각 Node에 node-exporter 설치

위에 언급한대로 K8s의 Node Exporter는 일반적인 Metric이 수집되므로, Alert Rule을 좀 더 구체화하기 위해 **각 Node에 node-exporter를 설치**한다.

설치는 간단한다. 최신의 패키지를 다운로드받고, 경로를 지정한 후 systemd Service 파일을 생성한 후 실행하면 된다.

```bash
# mkdir /home/node-exporter; cd /home/node-exporter
# wget https://github.com/prometheus/node_exporter/releases/download/v1.1.2/node_exporter-1.1.2.linux-amd64.tar.gz
# tar xvf node_exporter-1.1.2.linux-amd64.tar.gz
# mv node_exporter-1.1.2.linux-amd64 node_exporter
```
systemd Service 파일의 내역은 다음과 같다.

```bash
# cat /etc/systemd/system/node_exporter.service
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=nobody
ExecStart=/home/node-exporter/node_exporter/node_exporter --collector.filesystem.ignored-mount-points=^/(sys|proc|dev|run)($|/)

[Install]
WantedBy=default.target

```
> /home/node-exporter/node_exporter/ 경로에 주의해야하며, **--collector.filesystem.ignored-mount-points**는 굳이 수집할 필요가 없다고 판단된 **메모리/장치/임시 파티션** 들이다.

위와 같이 설정이 완료되었으면, reload를 수행하고 시작 및 활성화를 진행한다.

```bash
# systemctl daemon-reload
# systemctl start node_exporter.service; systemctl enable node_exporter.service
```

그럼 다음과 같이 Node에 TCP/9100이 Listen하는 것을 확인할 수 있다.

```bash
# netstat -lnp |grep 9100
tcp6       0      0 :::9100                 :::*                    LISTEN      12870/node_exporter
```

마지막으로 Prometheus의 Scarape_config 설정에 `job_name`에 추가해줘야 한다.

```bash
# cat prometheus-config-map.yaml
...중략
      - job_name: 'ext-node_exporter'
        static_configs:
        - targets: ['172.24.0.222:9100', '172.24.0.223:9100', '172.24.0.224:9100', '172.24.0.225:9100']
```

