Blackbox exporter를 이용한 HTTP 모니터링
Prometheus에서는 Blackbox exporter 를 이용하여 외부에 있는 서비스의 HTTP/HTTPS, DNS, TCP, ICMP 모니터링을 할 수 있습니다. 이 포스트에서는 이중에 HTTP/HTTPS를 모니터링하는 방식을 간단하게 알아보도록 하겠습니다. Kubernetes 상에서 Prometheus를 사용하는 환경의 사용자를 대상으로 작성하였습니다.
실행환경
여기에서는 다음과 같은 환경에서 Blackbox exporter를 사용한 모니터링 실습을 진행합니다.
- Kubernetes
- Prometheus operator
Blackbox exporter 설정 파일 생성
웹 서비스 엔드포인트를 모니터링하기 위한 http
모듈을 구성하기 위해 Blackbox configuration 파일을 ConfigMap
으로 작성합니다.
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-blackbox-exporter
labels:
app: prometheus-blackbox-exporter
data:
blackbox.yaml: |
modules:
http_2xx:
http:
no_follow_redirects: false
preferred_ip_protocol: ip4
valid_http_versions:
- HTTP/1.1
- HTTP/2
valid_status_codes: []
prober: http
timeout: 5s
위 모듈은 HTTP 프로토콜을 통해 액세스했을 때 서비스에서 2xx HTTP 상태 코드를 반환하는지를 확인하는데 사용되는 http_2xx
라는 모듈을 작성한 것입니다. 설정값에 대한 상세한 내용은 다음 문서 에서 확인하실 수 있습니다.
Kubernetes에 Blackbox exporter 배포
Kubernetes에 배포할 수 있도록 Deployment와 Service를 작성합니다.
---
kind: Service
apiVersion: v1
metadata:
name: prometheus-blackbox-exporter
labels:
app: prometheus-blackbox-exporter
spec:
type: ClusterIP
ports:
- name: http
port: 9115
protocol: TCP
selector:
app: prometheus-blackbox-exporter
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus-blackbox-exporter
labels:
app: prometheus-blackbox-exporter
spec:
replicas: 1
selector:
matchLabels:
app: prometheus-blackbox-exporter
template:
metadata:
labels:
app: prometheus-blackbox-exporter
spec:
restartPolicy: Always
containers:
- name: blackbox-exporter
image: "prom/blackbox-exporter:v0.15.1"
imagePullPolicy: IfNotPresent
securityContext:
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
args:
- "--config.file=/config/blackbox.yaml"
resources:
{}
ports:
- containerPort: 9115
name: http
livenessProbe:
httpGet:
path: /health
port: http
readinessProbe:
httpGet:
path: /health
port: http
volumeMounts:
- mountPath: /config
name: config
- name: configmap-reload
image: "jimmidyson/configmap-reload:v0.2.2"
imagePullPolicy: "IfNotPresent"
securityContext:
runAsNonRoot: true
runAsUser: 65534
args:
- --volume-dir=/etc/config
- --webhook-url=http://localhost:9115/-/reload
resources:
{}
volumeMounts:
- mountPath: /etc/config
name: config
readOnly: true
volumes:
- name: config
configMap:
name: prometheus-blackbox-exporter
다음 명령어를 실행하여 Blackbox exporter를 Kubernetes에 배포합니다. Prometheus operator가 위치한 monitoring Namespace를 지정하여 배포했습니다.
kubectl --namespace=monitoring apply -f blackbox-exporter.yaml
설치를 검증합니다.
kubectl --namespace=monitoring get all --selector=app=prometheus-blackbox-exporter
Blackbox exporter Test
port-forward
를 통해 Blackbox exporter Web UI에 접속하여 상태를 확인할 수 있습니다.
kubectl --namespace=monitoring port-forward svc/prometheus-blackbox-exporter 9115:9115
웹 브라우져에서 http://localhost:9115 에 접속하면 다음과 같이 Web UI를 확인하실 수 있습니다.
웹 브라우져에서 http://localhost:9115/probe?module=http_2xx&target=https://www.google.com 으로 접속하면 target URL에 대한 메트릭 정보를 확인하실 수 있습니다.
예를 들면 probe_success
메트릭이 1이면 성공이고 0이면 실패를 나타냅니다.
Prometheus 구성
위와 같이 검증을 마쳤다면, 이제 모니터링을 위한 설정을 Prometheus에 구성해줍니다.
- job_name: 'kube-api-blackbox'
scrape_interval: 1w
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- https://www.google.com
- http://www.example.com
- https://prometheus.io
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: prometheus-blackbox-exporter:9115 # The blackbox exporter.
위의 내용을 prometheus-additional.yaml
에 추가하고 다음과 같이 Secret
을 생성합니다.
PROMETHEUS_ADD_CONFIG=$(cat prometheus-additional.yaml | base64)
cat << EOF | kubectl --namespace=monitoring apply -f -
apiVersion: v1
kind: Secret
metadata:
name: additional-scrape-configs
type: Opaque
data:
prometheus-additional.yaml: $PROMETHEUS_ADD_CONFIG
EOF
생성된 Secret
을 Prometheus operator에 적용해줍니다.
kubectl --namespace=monitoring edit prometheuses k8s
...
spec:
additionalScrapeConfigs:
key: prometheus-additional.yaml
name: additional-scrape-configs
Prometheus Web UI에 접속하여 메트릭 수집과 타겟 등록이 정상적으로 등록되었는지 확인합니다.
kubectl --namespace=monitoring port-forward svc/prometheus-k8s 9090:9090
정상적으로 Prometheus에 등록되어 메트릭이 수집되는 것을 확인할 수 있을 것입니다.
Alert rule 추가
이제 알람 정책을 추가하여 장애발생 시에 알람을 받을 수 있도록 구성합니다.
kubectl --namespace=monitoring edit prometheusrules prometheus-k8s-rules
...
- name: blackbox-exporter
rules:
- alert: ProbeFailed
expr: probe_success == 0
for: 5m
labels:
severity: error
annotations:
summary: "Probe failed (instance {{ $labels.instance }})"
description: "Probe failed\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
- alert: SlowProbe
expr: avg_over_time(probe_duration_seconds[1m]) > 1
for: 5m
labels:
severity: warning
annotations:
summary: "Slow probe (instance {{ $labels.instance }})"
description: "Blackbox probe took more than 1s to complete\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
- alert: HttpStatusCode
expr: probe_http_status_code <= 199 OR probe_http_status_code >= 400
for: 5m
labels:
severity: error
annotations:
summary: "HTTP Status Code (instance {{ $labels.instance }})"
description: "HTTP status code is not 200-399\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
- alert: SslCertificateWillExpireSoon
expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 30
for: 5m
labels:
severity: warning
annotations:
summary: "SSL certificate will expire soon (instance {{ $labels.instance }})"
description: "SSL certificate expires in 30 days\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
- alert: SslCertificateHasExpired
expr: probe_ssl_earliest_cert_expiry - time() <= 0
for: 5m
labels:
severity: error
annotations:
summary: "SSL certificate has expired (instance {{ $labels.instance }})"
description: "SSL certificate has expired already\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
- alert: HttpSlowRequests
expr: avg_over_time(probe_http_duration_seconds[1m]) > 1
for: 5m
labels:
severity: warning
annotations:
summary: "HTTP slow requests (instance {{ $labels.instance }})"
description: "HTTP request took more than 1s\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
- alert: SlowPing
expr: avg_over_time(probe_icmp_duration_seconds[1m]) > 1
for: 5m
labels:
severity: warning
annotations:
summary: "Slow ping (instance {{ $labels.instance }})"
description: "Blackbox ping took more than 1s\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
Prometheus Web UI에서 Status => Rules
에서 alert rule이 등록되었는지 확인합니다.
Kubernetes API Server SSL 인증서 만료 알람
추가적으로 Kubernetes API Server의 SSL 인증서를 모니터링하여 만료되기 3달 전에 1주일에 1번씩 알람을 발송하는 설정을 추가해보도록 하겠습니다.
Kubernetes API Server Authentication을 위한 Blackbox exporter module 설정 추가
kubectl --namespace=monitoring edit configmap prometheus-blackbox-exporter
...
kube-api:
http:
method: GET
no_follow_redirects: false
preferred_ip_protocol: ip4
tls_config:
insecure_skip_verify: false
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
valid_http_versions:
- HTTP/1.1
- HTTP/2
valid_status_codes: []
prober: http
timeout: 5s
Prometheus configuration 추가
- job_name: 'kube-api-blackbox'
metrics_path: /probe
params:
module: [kube-api]
static_configs:
- targets:
- https://kubernetes.default.svc/api
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: prometheus-blackbox-exporter:9115 # The blackbox exporter.
Prometheus Secret에 적용
PROMETHEUS_ADD_CONFIG=$(cat prometheus-additional.yaml | base64)
cat << EOF | kubectl --namespace=monitoring apply -f -
apiVersion: v1
kind: Secret
metadata:
name: additional-scrape-configs
type: Opaque
data:
prometheus-additional.yaml: $PROMETHEUS_ADD_CONFIG
EOF
Alert rule 추가
kubectl --namespace=monitoring edit prometheusrules prometheus-k8s-rules
...
- name: k8s-api-server-cert-expiry
rules:
- alert: K8sAPIServerSSLCertExpiringAfterThreeMonths
expr: probe_ssl_earliest_cert_expiry{job="kube-api-blackbox"} - time() < 86400 * 90
for: 1w
labels:
severity: warning
annotations:
summary: "Kubernetes API Server SSL certificate will expire after three months (instance {{ $labels.instance }})"
description: "Kubernetes API Server SSL certificate expires in 90 days\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"