Ingress nginx
svc๋ฅผ ingress๋ก ์ธ๋ถ์ ์คํ
regex
https://kubernetes.github.io/ingress-nginx/user-guide/ingress-path-matching/
priority
In NGINX, regular expressions follow a first match policy, ๊ทธ๋ฌ๋ฏ๋ก ingress nginx๊ฐ ์ ๊ท์์ ๊ธธ์ด๋ฅผ ๊ธฐ์ค์ผ๋ก ์ญ์์ผ๋ก ์ ๋ ฌ์ ํํ controller์ ์ ๋ฐ์ดํธํฉ๋๋ค.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress-1
spec:
rules:
- host: test.com
http:
paths:
- path: /foo/bar
backend:
serviceName: service1
servicePort: 80
- path: /foo/bar/
backend:
serviceName: service2
servicePort: 80
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress-2
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: test.com
http:
paths:
- path: /foo/bar/(.+)
backend:
serviceName: service3
servicePort: 80
์ด ๊ฐ์ ํ์ผ์ด ๋๊ฐ๋ฉด ์๋์ ๊ฐ์ด ์ ๋ ฌ
location ~* ^/foo/bar/.+ {
...
}
location ~* "^/foo/bar/" {
...
}
location ~* "^/foo/bar" {
...
}
test.com/foo/bar/1 matches ~* ^/foo/bar/.+ and will go to service 3.
test.com/foo/bar/ matches ~* ^/foo/bar/ and will go to service 2.
test.com/foo/bar matches ~* ^/foo/bar and will go to service 1.
ํ ์คํธ๋ฅผ ์ํด ๋ค์๊ณผ๊ฐ์ yaml์ ๋ง๋ค์ด์ ์ ์ฉํ์ฟ๋ค.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress-1
namespace: default
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: c4.aaaa.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: front
port:
name: http
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress-2
namespace: default
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: c4.aaaa.com
http:
paths:
- path: /api(/|$)(.*)/i
pathType: Prefix
backend:
service:
name: api
port:
name: http
๊ฒฐ๊ณผ ์์ฑ๋ ํ์ผ์ด๋ค. ๊ฒฐ๋ก ๋ถํฐ ์ด์ผ๊ธฐํ๋ฉด ingress์ rewrite๋ฅผ ์ฐ๋ฉด ๊ทธ ์ธ๊ทธ๋ ์ค์๋ง ์ ์ฉ์ด ๋๋ค. ์๋๋ณด๋ฉด /api๋ถ๋ถ์๋ง rewrite $1 ๊ฐ ์ ์ฉ๋์ด ์๋ค.
## start server c4.aaaa.com
server {
server_name c4.aaaa.com ;
listen 80 ;
listen [::]:80 ;
listen 443 ssl http2 ;
listen [::]:443 ssl http2 ;
set $proxy_upstream_name "-";
ssl_certificate_by_lua_block {
certificate.call()
}
location ~* "^/api(/|$)(.*)" {
set $namespace "default";
set $ingress_name "test-ingress-2";
set $service_name "api";
set $service_port "http";
set $location_path "/api(/|${literal_dollar})(.*)";
set $global_rate_limit_exceeding n;
rewrite_by_lua_block {
lua_ingress.rewrite({
force_ssl_redirect = false,
ssl_redirect = true,
force_no_ssl_redirect = false,
preserve_trailing_slash = false,
use_port_in_redirects = false,
global_throttle = { namespace = "", limit = 0, window_size = 0, key = { }, ignored_cidrs = { } }
})
balancer.rewrite()
plugins.run()
}
...
port_in_redirect off;
set $balancer_ewma_score -1;
set $proxy_upstream_name "default-api-http";
set $proxy_host $proxy_upstream_name;
set $pass_access_scheme $scheme;
set $pass_server_port $server_port;
set $best_http_host $http_host;
set $pass_port $pass_server_port;
set $proxy_alternative_upstream_name "";
client_max_body_size 1m;
proxy_set_header Host $best_http_host;
# Pass the extracted client certificate to the backend
# Allow websocket connections
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Request-ID $req_id;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Host $best_http_host;
proxy_set_header X-Forwarded-Port $pass_port;
proxy_set_header X-Forwarded-Proto $pass_access_scheme;
proxy_set_header X-Forwarded-Scheme $pass_access_scheme;
proxy_set_header X-Scheme $pass_access_scheme;
# Pass the original X-Forwarded-For
proxy_set_header X-Original-Forwarded-For $http_x_forwarded_for;
# mitigate HTTPoxy Vulnerability
# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/
proxy_set_header Proxy "";
# Custom headers to proxied server
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffering off;
proxy_buffer_size 4k;
proxy_buffers 4 4k;
proxy_max_temp_file_size 1024m;
proxy_request_buffering on;
proxy_http_version 1.1;
proxy_cookie_domain off;
proxy_cookie_path off;
# In case of errors try the next upstream server before returning an error
proxy_next_upstream error timeout;
proxy_next_upstream_timeout 0;
proxy_next_upstream_tries 3;
rewrite "(?i)/api(/|$)(.*)" /$1 break; # <------------์ฌ๊ธฐ
proxy_pass http://upstream_balancer;
proxy_redirect off;
}
location ~* "^/" {
set $namespace "default";
set $ingress_name "test-ingress-1";
set $service_name "front";
set $service_port "http";
set $location_path "/";
set $global_rate_limit_exceeding n;
rewrite_by_lua_block {
lua_ingress.rewrite({
force_ssl_redirect = false,
ssl_redirect = true,
force_no_ssl_redirect = false,
preserve_trailing_slash = false,
use_port_in_redirects = false,
global_throttle = { namespace = "", limit = 0, window_size = 0, key = { }, ignored_cidrs = { } }
})
balancer.rewrite()
plugins.run()
}
port_in_redirect off;
set $balancer_ewma_score -1;
set $proxy_upstream_name "default-front-http";
set $proxy_host $proxy_upstream_name;
set $pass_access_scheme $scheme;
set $pass_server_port $server_port;
set $best_http_host $http_host;
set $pass_port $pass_server_port;
set $proxy_alternative_upstream_name "";
client_max_body_size 1m;
proxy_set_header Host $best_http_host;
# Pass the extracted client certificate to the backend
# Allow websocket connections
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Request-ID $req_id;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Host $best_http_host;
proxy_set_header X-Forwarded-Port $pass_port;
proxy_set_header X-Forwarded-Proto $pass_access_scheme;
proxy_set_header X-Forwarded-Scheme $pass_access_scheme;
proxy_set_header X-Scheme $pass_access_scheme;
# Pass the original X-Forwarded-For
proxy_set_header X-Original-Forwarded-For $http_x_forwarded_for;
# mitigate HTTPoxy Vulnerability
# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/
proxy_set_header Proxy "";
# Custom headers to proxied server
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffering off;
proxy_buffer_size 4k;
proxy_buffers 4 4k;
proxy_max_temp_file_size 1024m;
proxy_request_buffering on;
proxy_http_version 1.1;
proxy_cookie_domain off;
proxy_cookie_path off;
# In case of errors try the next upstream server before returning an error
proxy_next_upstream error timeout;
proxy_next_upstream_timeout 0;
proxy_next_upstream_tries 3;
proxy_pass http://upstream_balancer;
proxy_redirect off;
}
}
## end server c4.aaaa.com
์ฃผ์์ฌํญ
์๋์ ๊ฐ์ด ๋ง๋ค๋ฉด ๋ฌธ์ ๊ฐ ์์์ ์๋ค.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress-3
annotations:
nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
rules:
- host: test.com
http:
paths:
- path: /foo/bar/bar
backend:
serviceName: test-a
servicePort: 80
- path: /foo/bar/[A-Z0-9]{3}
backend:
serviceName: test-b
servicePort: 80
์์ฑ๋ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
location ~* "^/foo/bar/[A-Z0-9]{3}" {
...
}
location ~* "^/foo/bar/bar" {
...
}
test.com/foo/bar/bar ์ด๊ฑธ ์์ฒญํ๋ฉด ^/foo/bar/[A-Z0-9]{3} ์ฌ๊ธฐ์ ๊ฑธ๋ ค๋ฒ๋ฆฐ๋ค. ์ํ๋๋๋ก ์๋๋ค.
๋ ์๊ณ ์ถ์ผ๋ฉด ๋ค์ ๋งํฌ๋ฅผ ์ฝ์ด๋ณด๋ฉด๋๋ค.
log - 2022-09-11
๋ก๊ทธ๋ฅผ ์ปค์คํฐ๋ง์ด์ฆ ํ๊ณ ์ถ์ ๊ฒฝ์ฐ๊ฐ ์๋ค. ๊ด๋ จ ๋ํ๋จผํธ๋ ๋ค์์์ ์ป์์ ์๋ค.
log-format์ ํฐ ๋์์ด ์๋์๋ค. ๊ทธ๋์ 2๋ฒ์ ์ฐธ๊ณ ํด์ ์งํํ๋ค.
configmap์ ์ถ๊ฐํ๋ฉด ๋๋๊ฒ์ธ๋ฐ helm์ ์ฌ์ฉํ๋ค๋ณด๋ ์ด๋์ ์ถ๊ฐํ๋์ง ์ํ์ด ์์ด์ ๊ณ ์ํ๋ค.
heml์ฐจํธ์ ๋ณด๋ฉด ๋ค์ ๋ถ๋ถ์ด ์๋ค.
# Will add custom configuration options to Nginx https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/
# config: {} #์ด๋ถ๋ถ
config:
enable-underscores-in-headers: on
log-format-upstream: '$ingress_name "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] [$proxy_alternative_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status $req_id'
์ฃผ์์ฒ๋ฆฌํ ์๋์ฒ๋ผ ์ถ๊ฐ configmap๊ด๋ จ ๋ด์ฉ์ ์ถ๊ฐํ๋ค.
์ฌ๊ธฐ์ ์ฃผ์ํ ๊ฑด log-format-upstream
์ ์์ ํด์ผ๋๋ค.

์๋ ๋ณด์ด๋ log-format-stream์ ๊ฐ์ง๊ณ ์๋ฌด๋ฆฌ ํด๋ ์ ์ฉ๋์ง๊ฐ ์์๋ค. log-format-upstream
์ ์ฌ์ฉํ๋๊ฑธ ๋ณด๊ณ ์ ์ฉํด๋ณด๋ ์ ๋์๋ค.
๊ธฐ๋ณธ๊ฐ์ ๋ค์๊ณผ ๊ฐ๋ค.
$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] [$proxy_alternative_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status $req_id
๋์ ๊ฒฝ์ฐ๋ ๋ก๊ทธ์ ingress name์ ์ถ๊ฐ๋ก ๋ฃ๊ณ ์ถ์๋ค. ํ์ธํด๋ณด๋ 1๋ฒ ๋ฌธ์์์ ์ถ๊ฐ๋ก ์ฌ์ฉํ ์ ์๋ค๊ณ ํ๋ค.

๊ทธ๋์ ๋ค์๊ณผ ๊ฐ์ด ์ถ๊ฐํ๋ค.
# Will add custom configuration options to Nginx https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/
config:
enable-underscores-in-headers: on
log-format-upstream: '$ingress_name "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] [$proxy_alternative_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status $req_id'
๋์ ๊ฒฝ์ฐ๋ ๊ณ ๊ฐ ์์ดํผ๋ ์ค์ํ ์ํฉ์ด ์๋๊ณ ๋ก์ปฌ ์๊ฐ๋ ์ค์์น ์์์ ์ ๊ฑฐํ๊ณ ์ธ๊ทธ๋ ์ค ์ด๋ฆ์ ๋งจ ์ฒ์์ ๋ฃ์ด์ฃผ๊ณ ๋๋จธ์ง๋ ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํ๋ค.
๊ทธ๋ฆฌ๊ณ ๋ก๊ทธ๋ฅผ ํ์ธํด๋ณด๋ ๋ค์๊ณผ ๊ฐ์ด ์ ๋์ค๋๊ฒ์ ํ์ธํ๋ค.
loki์์ ํ์ธํด๋ณด๊ธฐ
์ด์ ๋ก๊ทธ๋ฅผ ๋กํค์์ ํ์ธํด๋ณด์.
# ๊ธฐ์กด
{namespace=~"nginx"} | pattern `<remote_addr> - - <time_local> "<method> <_> <_>" <status> <_> <_> "<_>" <_>` | status="400"
# ์์ ํ
{namespace=~"nginx"} | pattern `<ingress> "<method> <_> <_>" <status> <_> <_> "<_>" <_>` | status=~"[4-5].*" | ingress="IngeressName"
์ด๋ ๊ฒ ํ๋ฉด ingress name๋ณ๋ก ํํฐ๊ฐ ๊ฐ๋ฅํด์ง๋ค.
grafana dash board
์๋์ฒ๋ผ dashboard๋ฅผ ๋ง๋ค์ด ๋ณด์๋ค.
์์ ๋ ๊ทธ๋ํ๋ ํ๋ก๋ฉํ ์ฐ์ค์์ ๋ฉํธ๋ฆญ์ ๊ฐ์ ธ์์ ํํํ๊ณ ๋ง์ง๋ง ํ ์ด๋ธ์ ๋กํค์์ ๋ก๊ทธ๋ฅผ ๊ฐ์ ธ์์ ๋ฟ๋ ค์ค๋ค.

์๋ฌ๊ฐ ๋ฐ์ํ ๋ ์ด์ ๋ก๊ทธ๋ ํจ๊ป ๋ณผ์๊ฐ ์์ด์ ์ข๋ค.
๋ฐ์๋ณด๋ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 35,
"iteration": 1662994187189,
"links": [],
"liveNow": false,
"panels": [
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": {
"type": "prometheus",
"uid": "P1809F7CD0C75ACF3"
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 24,
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 6,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": false,
"total": false,
"values": false
},
"lines": true,
"linewidth": 2,
"nullPointMode": "connected",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.3.3",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "P1809F7CD0C75ACF3"
},
"exemplar": true,
"expr": "round(sum(irate(nginx_ingress_controller_requests{ingress=~\"$ingress\"}[2m])) by (ingress), 0.001)",
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
"thresholds": [],
"timeRegions": [],
"title": "Ingress Request Volume",
"tooltip": {
"shared": true,
"sort": 2,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"mode": "time",
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:57",
"format": "reqps",
"logBase": 1,
"show": true
},
{
"$$hashKey": "object:58",
"format": "short",
"logBase": 1,
"show": false
}
],
"yaxis": {
"align": false
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": {
"type": "prometheus",
"uid": "P1809F7CD0C75ACF3"
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 24,
"x": 0,
"y": 8
},
"hiddenSeries": false,
"id": 4,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": false,
"total": false,
"values": false
},
"lines": true,
"linewidth": 2,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.3.3",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "P1809F7CD0C75ACF3"
},
"exemplar": true,
"expr": "sum(rate(nginx_ingress_controller_requests{ingress=~\"$ingress\",status!~\"[4-5].*\"}[2m])) by (ingress) / sum(rate(nginx_ingress_controller_requests{ingress=~\"$ingress\"}[2m])) by (ingress)",
"interval": "10",
"legendFormat": "{{ingress}}",
"refId": "A"
}
],
"thresholds": [],
"timeRegions": [],
"title": "Ingress Success Rate (non-4|5xx responses)",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"mode": "time",
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:222",
"format": "percentunit",
"logBase": 1,
"show": true
},
{
"$$hashKey": "object:223",
"format": "short",
"logBase": 1,
"show": false
}
],
"yaxis": {
"align": false
}
},
{
"datasource": {
"type": "loki",
"uid": "P982945308D3682D1"
},
"gridPos": {
"h": 14,
"w": 24,
"x": 0,
"y": 15
},
"id": 2,
"options": {
"dedupStrategy": "none",
"enableLogDetails": true,
"prettifyLogMessage": false,
"showCommonLabels": false,
"showLabels": false,
"showTime": false,
"sortOrder": "Descending",
"wrapLogMessage": false
},
"pluginVersion": "8.3.3",
"targets": [
{
"datasource": {
"type": "loki",
"uid": "P982945308D3682D1"
},
"expr": "{namespace=~\"ingress-nginx|ingress-nginx-internal\"} | pattern `<ingress> \"<method> <_> <_>\" <status> <_> <_> \"<_>\" <_>`| status=~\"[4-5].*\" | ingress=\"$ingress\"",
"instant": false,
"range": true,
"refId": "log"
}
],
"title": "Http 4-5xx",
"type": "logs"
}
],
"schemaVersion": 34,
"style": "dark",
"tags": [],
"templating": {
"list": [
{
"current": {
"selected": false,
"text": "shop-ingress",
"value": "shop-ingress"
},
"datasource": {
"type": "prometheus",
"uid": "P1809F7CD0C75ACF3"
},
"definition": "label_values(ingress) ",
"hide": 0,
"includeAll": true,
"label": "ingress",
"multi": false,
"name": "ingress",
"options": [],
"query": {
"query": "label_values(ingress) ",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 2,
"type": "query"
}
]
},
"time": {
"from": "now-12h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Loggging",
"uid": "A-3q5wMVz",
"version": 9,
"weekStart": ""
}
log-format vs log-format-upstream
์์ง ์ ๋ชจ๋ฅด๋๋ฐ ์ด ๋ค์ด์ด๊ทธ๋จ์ด ์ข ๋์์ด ๋๋๋ฏ.

์ด๊ฑธ ํ๋ฒ ์ ์ฝ์ด๋ด์ผ๊ฒ๋ค. https://www.nginx.com/blog/logging-upstream-nginx-traffic-cdn77/ ๊ทธ๋์ ๋ ingress-nginx๋ ์ upstream๋ก๊ทธ๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ ๊ฐ? ํ๋ก์๋๊น ๋ง๋๊ฒ๋ ๊ฐ๊ณ ...
helmchart ์ฌ์ฉ์ค configmap์ค์
helmchart๋ฅผ ์ฌ์ฉ์ค์ configmap์ ์ค์ ํด์ผํ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค. ๋งค๋ด์ผ๋ฑ์ด ์ ๋ถ configmap๋ง ๋์ค๋ฉด ๋ค์์ฒ๋ผ ํ์.
helm chart ์ config์ ์ค์ ์ ๋ฃ์ผ๋ฉด ๋๋ค.
# Will add custom configuration options to Nginx https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/
config:
enable-underscores-in-headers: on
์ฌ๊ธฐ์ ์ฌ์ฉํ ์ ์๋ ํญ๋ชฉ๋ค์ ๋ค์ ํ์ด์ง์์ ํ์ธํ๋ค.
๊ฝค ๋ง์ ์ต์ ๋ค์ด ์ฌ๊ธฐ์์ ์ฒ๋ฆฌํ ์ ์๋ค.
values ํ์ผ์ ๋ณ๊ฒฝํ argocd์์ ๋ก๋ฉ์ ํ๊ฑฐ๋ ์ ์ฉ์ ํ๋ฉด pod์ ์๋์ผ๋ก config๊ฐ reload๊ฐ ๋๋ค. ์ค์ํ๊ฒ์ pod๊ฐ ์ฌ์์ ๋์ง ์๋๋ค. ์ค์ ๋ง ์๋์ผ๋ก ๋ฆฌ๋ก๋ ๋๋ค.
๋ง์ฝ ์ค์ ์ด ์๋ชป๋๋ฉด test fail
๋๋ฉด์ ๋ฆฌ๋ก๋ฉ ํ์ง ์๋๋ค.
todo
log-format-upstream ๊ณผ log-format์ ์ฐจ์ด์ ํ์ ํ๊ธฐ
dashboard๋ฅผ kube-prometheus์์ ๋ฃ์ด์ค์ผํ๋ค.
Last updated
Was this helpful?