iptables๋ฅผ ์์งํ์ฌ Grafana๋ก ํํํ๋ ๋ฐฉ๋ฒ์ ์์๋ด ๋๋ค.
CloudNet@์์ ์งํํ๊ณ ์๋ K8s Advanced Network Study(์ดํ, KANS)๋ฅผ ํตํด ํ์ตํ ๋ด์ฉ์ ์ ๋ฆฌํฉ๋๋ค.
0. ํ๊ฒฝ ๊ตฌ์ฑ (kind)
์์ฑ์๊ฐ ์ด์๋ก featureGates, ConfigPatches, networking ์ค์ ์ค๋ช ์ ์คํต…ํฉ๋๋ค.
a. 1 Master, 3 Slave ํ๊ฒฝ ๊ตฌ์ฑ
cat <<EOT> kind-svc-1w.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
featureGates:
"InPlacePodVerticalScaling": true
"MultiCIDRServiceAllocator": true
nodes:
- role: control-plane
labels:
mynode: control-plane
topology.kubernetes.io/zone: ap-northeast-2a
extraPortMappings:
- containerPort: 30000
hostPort: 30000
- containerPort: 30001
hostPort: 30001
- containerPort: 30002
hostPort: 30002
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
apiServer:
extraArgs:
runtime-config: api/all=true
controllerManager:
extraArgs:
bind-address: 0.0.0.0
etcd:
local:
extraArgs:
listen-metrics-urls: http://0.0.0.0:2381
scheduler:
extraArgs:
bind-address: 0.0.0.0
- |
kind: KubeProxyConfiguration
metricsBindAddress: 0.0.0.0
- role: worker
labels:
mynode: worker1
topology.kubernetes.io/zone: ap-northeast-2a
- role: worker
labels:
mynode: worker2
topology.kubernetes.io/zone: ap-northeast-2b
- role: worker
labels:
mynode: worker3
topology.kubernetes.io/zone: ap-northeast-2c
networking:
podSubnet: 10.10.0.0/16
serviceSubnet: 10.200.1.0/24
EOT
kind create cluster --config kind-svc-1w.yaml --name myk8s --image kindest/node:v1.31.0
b. ๊ธฐ๋ณธ ํด ์ค์น
docker exec -it myk8s-control-plane sh -c 'apt update && apt install tree psmisc lsof wget bsdmainutils bridge-utils net-tools ipset ipvsadm nfacct tcpdump ngrep iputils-ping arping git vim arp-scan -y'
1. prometheus stack ์ค์น (helm)
a. repository ์ถ๊ฐ ๋ฐ ๊ตฌ์ฑ
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
cat <<EOT > monitor-values.yaml
prometheus:
prometheusSpec:
podMonitorSelectorNilUsesHelmValues: false
serviceMonitorSelectorNilUsesHelmValues: false
nodeSelector:
mynode: control-plane
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Equal"
effect: "NoSchedule"
grafana:
defaultDashboardsTimezone: Asia/Tokyo
adminPassword: kans7969
service:
type: NodePort
nodePort: 30002
nodeSelector:
mynode: control-plane
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Equal"
effect: "NoSchedule"
defaultRules:
create: false
alertmanager:
enabled: false
EOT
b. ์ค์น
kubectl create ns monitoring
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 62.3.0 -f monitor-values.yaml --namespace monitoring
c. prometheus ์ฝ์ ์ ์
์๋ก์ด ํฐ๋ฏธ๋์ ์ด์ด, port-forwarding์ ํตํด ์ ์ํฉ๋๋ค.
# New Terminal
kubectl port-forward svc/kube-prometheus-stack-grafana -n monitoring 9090:9090

๊ณจ์น ์ํ etcd ๋ง์ ๋ถ์ ๊ฑธ ์ ์ ์์ต๋๋ค.
์ฌ์ค, ๋ฐ๋ก ์ถฉ๋๋ ์ค ์๊ณ , ๊ธฐ๋ํ๋๋ฐ… ์ ๋ฐ.
์ถฉ๋๋๋ค๋ฉด, ์ฃผ์ํ ์ด์๋ ๋งจ ์์ kind์์ ์ง์ ํ port ๋ถ์ผ์น์
๋๋ค.
์๋๋ฅผ ์ฐธ๊ณ ํ์ฌ ๊ณ ์ณ๋ณด์ธ์.
helm upgrade --install \
--namespace monitoring --create-namespace \
--repo https://prometheus-community.github.io/helm-charts \
kube-prometheus-stack kube-prometheus-stack --values - <<EOF
kubeEtcd:
service:
targetPort: 2381
EOF
2. Grafana dashboard ํ์ธ
Grafana์ ์ ์ํด๋ด ์๋ค.
kube-prometheus-stack์ ๊ธฐ๋ณธ ์ค์นํ๋ฉด, node-exporter์ grafana๋ ํจ๊ป ์ค์น๋ฉ๋๋ค.
a. ์ ์ ์ ๋ณด ํ์ธ
์ฐ์ ์ ์ํ ID์ ํจ์ค์๋๋ฅผ ์์์ผ๊ฒ ์ฃ .
kubectl get secret -n monitoring kube-prometheus-stack-grafana -o jsonpath="{.data.admin-user}" | base64 --decode ; echo
# admin
kubectl get secret -n monitoring kube-prometheus-stack-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
# kans7969
…์ด๋ ๊ฒ๋ ์ํํ๊ฑธ ๋ค๋ค ์ฐ๊ณ ์๋ค๋ ์กด๊ฒฝํฉ๋๋ค.
b. Port ํ์ธ
์์์ Grafana์ ๊ฒฝ์ฐ NodePort๋ก ๋ฏธ๋ฆฌ ์ง์ ํ๊ธฐ ๋๋ฌธ์, ํ๋ก๋ฉํ ์ฐ์ค ๋์๋ ๋ฌ๋ฆฌ ๋ณ๋์ port-forwarding ์ค์ ์ ํ์์์ต๋๋ค.
kubectl get svc -A -owide | grep NodePort
# monitoring kube-prometheus-stack-grafana NodePort 10.200.1.25 <none> 80:30002/TCP 101m app.kubernetes.io/instance=kube-prometheus-stack,app.kubernetes.io/name=grafana
์์ ๊ฒฝ์ฐ์๋ kind๋ฅผ ๊ตฌ์ฑํ, ์ปดํจํฐ์ ๋ธ๋ผ์ฐ์ ์์ localhost:30002๋ก ์ ์ํ๋ฉด ๋ฉ๋๋ค.
c. Dashboard ํ์ธ
- Dashboard(13674): Grafana Labs
์ ์ญ์. ๋ญ๊ฐ ๋ง์ด ๋ถ์กฑํ์ฃ ? ๊ฐ ๋ ธ๋์ iptables rule๊ณผ io up/down์ด ํ์ธ์ด ์๋๋ค์.

์ด์ ์ด๊ฑธํด์ผ๋ฉ๋๋ค.
3. iptables exporter ์ค์
a. ์์ธ ์๋ด
๊ฐ๋จํฉ๋๋ค. ํด๋น ๋์๋ณด๋ ํ
ํ๋ฆฟ ์๋ด๋ฌธ์, ํ
ํ๋ฆฟ ์์ฑ์๊ฐ ๋ฐ๋ก ํฌํฌ๋ ์ ์์ฑํ node-exporter๋ฅผ ์๋ดํ๊ณ ์๊ธฐ ๋๋ฌธ์ด์ฃ . Wow!
๊ทธ๋๋ ์๋ด๋ผ๋ ์์ด์ ๋คํ์
๋๋ค. ํ๋ฒ ๋ณผ๊น์?
- (LeiShi1313/node_exporter): https://github.com/LeiShi1313/node_exporter/commits/master/

๋ญ๊ฐ ๋ฐ๋๊ฑฐ๋ ๋ณด์ด๊ณ … ์๋ฌด๋๋ ์ด๋ป๊ฒ๋ yaml์ ๋๋ ค๋ฃ์ด์ผํ๋ ๊ฑธ๊น… ๊ณ ๋ฏผํ๊ฒ ๋ฉ๋๋ค.
b. ๊ณ ๋ฏผํด๋ด ์๋ค, ๋ฌด์์?
helm์ ์ฐ๋ ๋๋ค์์ ์ฌ์ฉ์๋ค์ ์ ํ์๋ ์๊ณ … ์ ๊ฒจ๋ฅผ๋ ์๋ ์ฌํญ์ธ๋ฐ,
ํฌ๋ฆ ์ฐจํธ์๋ ๊ทธ ๋ญ๋, dependency๋ผ๋ ๊ฒ์ด ์กด์ฌํ๋๋ฐ์.
์ต์ ๋ฌธ์ ๊ธฐ์ค ์๋์ ๊ฐ์ด ์ ๋ง๋ค ์์กด์ฑ์ด์ง. ์์กด์ฑ์ด ๊ฑธ๋ ค์๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.

์ ์ฝ๊ณ ๋ ๋ฏธ๊ถ ์์ผ๋ก ๋น ์ง๋๋ค. ์์กด์ฑ ์ด๋ฆ์ด prometheus-node-exporter … ์ ํฐ์ผ๋ฌ๋ค์.
c. ๊ทธ๋๋ ๊ทธ๋ฅ ๋ ๋ณผ๊น
์ผ๋จ ์ง๊ธ๊น์ง ํ์ด ์๊ฐ์ด ์๊น์ฐ๋, ๊ณ์ ๋ด ๋๋ค.
๋์๋ณด๋ ๊ธฐ์ค์ผ๋ก ๋๋ฝ๋ ์์ ฏ์์ ์ด๋ ํ ๊ฐ์ ์์ฒญํ๋์ง ์ดํด๋ด ๋๋ค.
increase(node_iptables_download_bytes_total{job=~"$job",instance=~"$instance"}[$__range])increase(node_iptables_upload_bytes_total{job=~"$job",instance=~"$instance"}[$__range])irate(node_v2ray_download_bytes_total{job=~"$job",instance=~"$instance",dimension=~"$dimension",target=~"$target"}[5m])irate(node_v2ray_upload_bytes_total{job=~"$job",instance=~"$instance",dimension=~"$dimension",target=~"$target"}[5m])irate(node_v2ray_download_bytes_total{job=~"$job",instance=~"$instance",dimension=~"$dimension",target=~"$target"}[5m])irate(node_iptables_download_bytes_total{job=~"$job",instance=~"$instance",chain=~"$dimension",rule=~"$target"}[5m])
์ญ์, ๋๋ฝ๋ ์์ ฏ์ ์ฃ๋ค ์ปค๋ฐ๋ด์ญ๊ณผ ์ฐ๋๋ ๋ด์ฉ์ด๋ค์. ํนํ v2ray ๋ํ, ๋ฐ๋ก GitHub repository๊ฐ ์์ต๋๋ค.
์ด์ ์ ํ์ง๋ ์ผ๋ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
p8s์์ target ์ดํด๋ดค์๋ ์๋ ๊ฑธ ๋ณด๋, ํ์ฑํํด์๋๋ฉด okay ์๋๋ฉด… GG
A์) ๊ธฐ์กด node-exporter๋ฅผ ํ์ฑํํ์ฌ ์ฌ์ฉ.
๋ง์ด ๋์ง ์์. ์๋ณธ node-exporter์๋ v2ray ๊ฐ์ ๊ฑด ์์ง ์์์.B์) ๊ธฐ์กด helm ์ฐจํธ๋ฅผ ์์ ํ์ฌ node-exporter ์ฐธ์กฐ ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉ.
๊ทธ๋ฐ, ํํ๊ฑฐ ํ๋ฉด ์๋ ๊ฒ ๊ฐ๋ค์.- C์) ๋ญ๊ฐ ์ ๋นํ๊ณ ๋๋ผ์ด Discussion์ ํตํด, ๊ทธ์ ๋ ์ฝ์งํ๊ธฐ…
์ด๊ฑธ๋ก… ํด๋ณผ๊ป์.
์ด๊ฑธ ๋ณด๋, ๋ญ๊ฐ ์ฌ์ฐ์ ๋๋ผ๊ธฐ ์์ํฉ๋๋ค. ๋นจ๋ฆฌ ๋๋ง์ณ
This horrifying cron one liner when set as a cron simulates an iptables exporter. At least on debian buster/stretch it does. It gives more or less the same output as the dedicated iptables exporter. It just uses awk to process the output of iptables-save -c into something prometheus can understand, and pops it in the folder the node exporter monitors.
SCRAPE_INTERVAL=15
OFFSET_INTERVAL=5
* * * * * root sleep $OFFSET_INTERVAL; for i in $(seq $SCRAPE_INTERVAL $SCRAPE_INTERVAL 60); do /usr/sbin/iptables-save -c | grep -v '^#' | grep -v 'COMMIT' | sed -e s'/\[//g;s/\]//g' | awk -F'[ :]' '{ if($0 ~ /\*/) { table=$0; gsub("^*","",table); } else if($0 ~ /^\:/){ print "iptables_rule_bytes_total{chain=\"" $2 "\",policy=\"" $3 "\",table=\"" table "\"} " $5 "\niptables_rule_packets_total{chain=\"" $2 "\",policy=\"" $3 "\",table=\"" table "\"} " $4; } else { rule=$5; for(i=6;i<=NF;i++){rule=rule" "$i} print "iptables_rule_bytes_total{chain=\"" $4 "\",rule=\"" rule "\",table=\"" table "\"} " $2 "\niptables_rule_packets_total{chain=\"" $4 "\",rule=\"" rule "\",table=\"" table "\"} " $1; } }' > /var/lib/prometheus/node-exporter/iptables.prom; echo "iptables_scrape_success $(date +\%s)" >> /var/lib/prometheus/node-exporter/iptables.prom; sleep $SCRAPE_INTERVAL; done
์์ ์จ ๋ง์์ผ๋ก ๋๋ค๋, ๊ทธ๋ฅ ๋น ๋ฅด๊ฒ ๋ค๋ฅธ ๊ฑธ ๋ ์ฐพ์๋ด
๋๋ค.
๊ถํ ์ด์ผ๊ธฐ๊ฐ ๋์ค๋ค์.$(date +\%s)๋ฅผ ์ฐ๋ฉด ๊ทธ ๋ก๊ทธ๋ ์กฐ์๋๊ป์ ์์ ์ค๊ฑฐ๋๋ฉฐ
์ฌ์ค ๋ญ discussion์์ permission ์ธ๊ธ๋๊ธธ๋ ์ฐพ์๋ณด๋, pypi/iptables-exporter๋ ๋์ค๊ณ ๋ญ๊ฐ ์ด์ง๋ฌ์๋ณด์ด๋ค๊ฐ ๋ช ๋ฃํ๊ฒ ๊ถํ ์ธ๊ธ๋๋๊ฑธ ๋ด์ ํด๋ณด๊ธฐ๋ก ํ์ต๋๋ค.
d. Do… It
๊ถํ
- ์ด 3๊ฐ์ ๊ถํ์ ํ์ฉํด์ผํฉ๋๋ค.
- CAP_DAC_READ_SEARCH
- CAP_NET_ADMIN
- CAP_NET_RAW
๊ถํ์ ์ ์ฉ
retailnext/iptables_exporter- GitHub
- ์ฒซ ๊ตฌ์ ์ ๋ณด๋ฉด, ์น์ ํ๊ฒ systemd ์ต์ ์ฌ์ค์ ์ด ํ์ํ๋ค๊ณ ํฉ๋๋ค.
Unfortunately, iptables-save (which this exporter uses) doesn’t work without special permissions.
Including the following systemd [Service] options will allow this exporter to work without running it as root:
CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_NET_ADMIN CAP_NET_RAW
AmbientCapabilities=CAP_DAC_READ_SEARCH CAP_NET_ADMIN CAP_NET_RAW
kbknapp/iptables_exporter- GitHub
- ๊ถํ ๋ถ๋ถ ์ธ์๋ ๋ฐ๋ผํด๋ณผ๋ง ํ๊ณ , ์ปค๋ฐ ๊ธฐ์ค ์ต์ ์ด์ด์ ์๋๋ฅผ ํด๋ด ๋๋ค.
- buggy ํ ๊ฒ์ ์ด์ฉ ์ ์์ ๋ฏ ํฉ๋๋ค.
iptables_exporter ์ค์น
๊ฐ๋ง ์๊ฐํด๋ณด๋ ์ด์ฐจํผ root๋ก ์ ์ํ๋, ๋๋์ง ์ ๋๋ง ๋ณด๋ ๊ฑธ๋ก ํด๋ด ๋๋ค.
rust-toolkit์ ์๊ฒฝํ๋, ๋ฐ์ด๋๋ฆฌ(x86_64) ํ์ผ์ ๋ฐ์์ ํด๋ด
๋๋ค.
docker exec -it myk8s-worker bash
root@myk8s-worker:/# echo $PATH
# /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
root@myk8s-worker:/# cd /tmp
root@myk8s-worker:/tmp# curl https://github.com/kbknapp/iptables_exporter/releases/download/v0.4.0/iptables_exporter-v0.4.0-x86_64-linux-musl.tar.gz -o iptables_exporter-v0.4.0-x86_64-linux-musl.tar.gz -L
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 3114k 100 3114k 0 0 436k 0 0:00:07 0:00:07 --:--:-- 641k
root@myk8s-worker:/tmp# tar -xvf iptables_exporter-v0.4.0-x86_64-linux-musl.tar.gz ./iptables_exporter
./iptables_exporter
root@myk8s-worker:/tmp# mv iptables_exporter /usr/bin
root@myk8s-worker:/tmp# iptables_exporter -V
iptables_exporter v0.4.0 (f8d6fca92a)
root@myk8s-worker:/tmp# rm *
root@myk8s-worker:/tmp# cd -
/
root@myk8s-worker:/#
systemD ๋ฑ๋ก
์ด์ background๋ก ์คํํ ์ ์๋๋ก systemd์ ๋ฑ๋กํฉ๋๋ค.
root@myk8s-worker:/# cat <<EOT > /etc/systemd/system/iptables_exporter.service
[Unit]
Description=iptables_exporter
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/iptables_exporter
Restart=always
RestartSec=5
CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_NET_ADMIN CAP_NET_RAW
AmbientCapabilities=CAP_DAC_READ_SEARCH CAP_NET_ADMIN CAP_NET_RAW
[Install]
WantedBy=multi-user.target
EOT
# permission
root@myk8s-worker:/# chmod a+x /etc/systemd/system/iptables_exporter.service
reload ํ, ์ํ ์ฒดํฌ
root@myk8s-worker:/# systemctl daemon-reload
root@myk8s-worker:/# service status iptables_exporter
status: unrecognized service
root@myk8s-worker:/# service iptables_exporter status
โ iptables_exporter.service - iptables_exporter
Loaded: loaded (/etc/systemd/system/iptables_exporter.service; disabled; preset: enabled)
Active: inactive (dead)
root@myk8s-worker:/# service iptables_exporter start
root@myk8s-worker:/# service iptables_exporter status
โ iptables_exporter.service - iptables_exporter
Loaded: loaded (/etc/systemd/system/iptables_exporter.service; disabled; preset: enabled)
Active: active (running) since Sun 2024-09-29 17:06:54 UTC; 2s ago
Main PID: 8697 (iptables_export)
Tasks: 1 (limit: 5729)
Memory: 1.3M
CPU: 13ms
CGroup: /system.slice/iptables_exporter.service
โโ8697 /usr/bin/iptables_exporter
Sep 29 17:06:54 myk8s-worker systemd[1]: Started iptables_exporter.service - iptables_exporter.
Sep 29 17:06:54 myk8s-worker iptables_exporter[8697]: 2024-09-29T17:06:54.686186Z INFO iptables_exporter: Registering metrics...
Sep 29 17:06:54 myk8s-worker iptables_exporter[8697]: 2024-09-29T17:06:54.686280Z INFO iptables_exporter: Spawning server...
Sep 29 17:06:54 myk8s-worker iptables_exporter[8697]: 2024-09-29T17:06:54.686338Z INFO iptables_exporter: Collecting iptables metrics...
Sep 29 17:06:54 myk8s-worker iptables_exporter[8697]: 2024-09-29T17:06:54.687570Z INFO iptables_exporter: Collecting iptables metrics...
root@myk8s-worker:/# exit
scrape_config ์ค์
์ด์ ์์์ ์ฌ์ฉํ๋, monitor-values.yaml์ ์์ ํฉ๋๋ค.
cat <<EOT > monitor-values.yaml
prometheus:
prometheusSpec:
podMonitorSelectorNilUsesHelmValues: false
serviceMonitorSelectorNilUsesHelmValues: false
nodeSelector:
mynode: control-plane
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Equal"
effect: "NoSchedule"
additionalScrapeConfigs: |
- job_name: 'iptables'
static_configs:
- targets: ['localhost:9455', '172.18.0.3:9455']
relabel_configs:
- source_labels: [ '__address__' ]
regex: '(.*):\d+'
target_label: instance
grafana:
defaultDashboardsTimezone: Asia/Tokyo
adminPassword: kans7969
service:
type: NodePort
nodePort: 30002
nodeSelector:
mynode: control-plane
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Equal"
effect: "NoSchedule"
defaultRules:
create: false
alertmanager:
enabled: false
EOT
helm upgrade --install \
--namespace monitoring --create-namespace \
--repo https://prometheus-community.github.io/helm-charts \
kube-prometheus-stack kube-prometheus-stack --values monitor-values.yaml
๋ค์ ์ดํด๋ณด๋.. ์ญ์ ์๋ฌ๊ฐ ๋์๋ ๊ตฐ์.
ํฌํธ ์ ์ด๋ ค์์ด์ ๊ทธ๋ฐ๊ฑฐ ๊ฐ์๋ฐ, ์ผ๋จ ์์ผ๊ฒ ์ต๋๋ค.

Reference
https://medium.com/@charled.breteche/kind-fix-missing-prometheus-operator-targets-1a1ff5d8c8ad
https://sbcode.net/prometheus/prometheus-node-exporter-2nd/
https://www.crybit.com/install-and-configure-node-exporter/
https://docs.redhat.com/ko/documentation/red_hat_enterprise_linux/7/html/system_administrators_guide/sect-managing_services_with_systemd-unit_files#sect-Managing_Services_with_systemd-Unit_File_Create
kkumtree
Source code on GitHub
ยฉ 2025 kkumtree and contributors All rights reserved.
Licensed under
CC BY-NC-ND 4.0