대시보드 노출하기
대시보드 노출하기 (Exposing the Dashboard)
매번 linkerd viz dashboard를 실행하는 대신 인그레스로 Linkerd 대시보드를 외부에 노출하는 방법을 인그레스 컨트롤러별로 알려드려요.
본문
매번 무슨 일이 일어나고 있는지 보려고 linkerd viz dashboard를 사용하는 대신, 인그레스를 통해 대시보드를 노출할 수 있습니다. grafana.url 설정으로 Linkerd viz에 연결해 두었다면 Grafana도 함께 노출돼요.
- Nginx (기본 인증 포함)
- oauth2-proxy와 함께 쓰는 Nginx
- Traefik
- Ambassador
- DNS 리바인딩 보호 / Host 요구사항 조정
Nginx
기본 인증을 사용하는 Nginx
샘플 인그레스 정의는 다음과 같아요:
`apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: web-ingress-auth
namespace: linkerd-viz
data:
auth: YWRtaW46JGFwcjEkbjdDdTZnSGwkRTQ3b2dmN0NPOE5SWWpFakJPa1dNLgoK
---
# apiVersion: networking.k8s.io/v1beta1 # for k8s
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
namespace: linkerd-viz
annotations:
nginx.ingress.kubernetes.io/upstream-vhost: $service_name.$namespace.svc.cluster.local:8084
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header Origin "";
proxy_hide_header l5d-remote-ip;
proxy_hide_header l5d-server-id;
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: web-ingress-auth
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"
spec:
ingressClassName: nginx
rules:
- host: dashboard.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 8084
`
이렇게 하면 대시보드가 dashboard.example.com에 노출되고 admin/admin을 사용하는 기본 인증으로 보호됩니다. 사용자 이름과 비밀번호를 바꾸는 방법은 ingress-nginx 문서를 참고하세요.
oauth2-proxy와 함께 쓰는 Nginx
기본 인증보다 더 안전한 대안은 oauth2-proxy 같은 인증 프록시를 사용하는 것입니다.
Kubernetes에서 oauth2-proxy를 배포·구성하는 방법에 대한 참고 자료는 Don Bowman의 이 블로그 포스트를 보세요.
tl;dr: oauth2-proxy를 이 Helm 차트로 배포한다면 다음 값들이 필요합니다:
`config:
existingSecret: oauth2-proxy
configFile: |-
email_domains = [ "example.com" ]
upstreams = [ "file:///dev/null" ]
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: nginx
path: /oauth2
ingress:
hosts:
- linkerd.example.com
`
여기서 oauth2-proxy 시크릿에는 client-id, client-secret, cookie-secret 같은 필수 oauth2 설정이 들어 있어야 합니다.
설정을 마치면 샘플 인그레스는 이렇게 됩니다:
`# apiVersion: networking.k8s.io/v1beta1 # for k8s
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
namespace: linkerd-viz
annotations:
nginx.ingress.kubernetes.io/upstream-vhost: $service_name.$namespace.svc.cluster.local:8084
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header Origin "";
proxy_hide_header l5d-remote-ip;
proxy_hide_header l5d-server-id;
nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri
nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth
spec:
ingressClassName: nginx
rules:
- host: linkerd.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 8084
`
Traefik
샘플 인그레스 정의는 다음과 같아요:
`apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: web-ingress-auth
namespace: linkerd-viz
data:
auth: YWRtaW46JGFwcjEkbjdDdTZnSGwkRTQ3b2dmN0NPOE5SWWpFakJPa1dNLgoK
---
# apiVersion: networking.k8s.io/v1beta1 # for k8s
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
namespace: linkerd-viz
annotations:
ingress.kubernetes.io/custom-request-headers: l5d-dst-override:web.linkerd-viz.svc.cluster.local:8084
traefik.ingress.kubernetes.io/auth-type: basic
traefik.ingress.kubernetes.io/auth-secret: web-ingress-auth
spec:
ingressClassName: traefik
rules:
- host: dashboard.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 8084
`
이렇게 하면 대시보드가 dashboard.example.com에 노출되고 admin/admin을 사용하는 기본 인증으로 보호됩니다. 사용자 이름과 비밀번호를 바꾸는 방법은 Traefik 문서를 참고하세요.
Ambassador
Ambassador는 서비스의 주석으로 매핑(mapping)을 정의해 동작합니다.
아래 주석은 대시보드를 dashboard.example.com에 노출합니다.
`annotations:
getambassador.io/config: |-
---
apiVersion: getambassador.io/v2
kind: Mapping
name: web-mapping
host: dashboard.example.com
prefix: /
host_rewrite: web.linkerd-viz.svc.cluster.local:8084
service: web.linkerd-viz.svc.cluster.local:8084
`
DNS 리바인딩 보호
DNS-리바인딩 공격을 막기 위해, 대시보드는 Host 헤더가 localhost, 127.0.0.1 또는 서비스 이름 web.linkerd-viz.svc가 아닌 요청을 거부합니다.
이 보호는 Grafana 대시보드에도 적용된다는 점을 알아두세요.
위의 ingress-nginx 설정은 nginx.ingress.kubernetes.io/upstream-vhost 주석으로 업스트림 Host 헤더를 올바르게 설정합니다. 반면 Traefik은 그런 옵션을 제공하지 않으므로, 아래에서 설명하는 대로 필요한 Host를 직접 설정해야 합니다.
Host 요구사항 조정하기
HTTP 클라이언트(인그레스든 뭐든)가 Host 헤더를 다시 쓸 수 없다면, 대시보드 서버가 사용하는 검증 정규식을 바꿀 수 있습니다. 이 정규식은 web 배포의 enforced-host 컨테이너 인자로 제공됩니다.
Helm으로 Linkerd를 관리한다면 enforcedHostRegexp 값으로 host를 설정할 수 있어요.
또 다른 방법은 Customizing Installation에서 설명한 대로 Kustomize를 쓰는 것입니다. 다음과 같은 오버레이를 쓰면 되죠:
`apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
template:
spec:
containers:
- name: web
args:
- -linkerd-controller-api-addr=linkerd-controller-api.linkerd.svc.cluster.local:8085
- -linkerd-metrics-api-addr=metrics-api.linkerd-viz.svc.cluster.local:8085
- -cluster-domain=cluster.local
- -grafana-addr=grafana.grafana
- -controller-namespace=linkerd
- -viz-namespace=linkerd-viz
- -log-level=info
- -enforced-host=^dashboard\.example\.com$
`
Host 헤더 검사를 완전히 비활성화하려면 -enforced-host에 catch-all 정규식 .*을 쓰면 됩니다.
더 알아보기 (Learn more)
- linkerd viz 대시보드 명령 문서
- 사용자 지정 설치 (Customizing Installation)