드라이 런
드라이 런 (Dry Run)
이 작업은 새 실험용 어노테이션 istio.io/dry-run을 사용해서 정책을 실제로 시행하지 않고 드라이 런하는 Istio 인가 정책을 설정하는 방법을 보여드려요. 이 기능은 개발자/고급 사용자를 대상으로 하며 Alpha 단계로 간주돼요.
출처: Istio 문서
본문
[!note] 이 기능은 개발자/고급 사용자를 대상으로 하며 Alpha 단계로 간주돼요. 이 작업은 새 실험용 어노테이션
istio.io/dry-run을 사용해서 정책을 실제로 시행하지 않고 드라이 런하는 Istio 인가 정책을 설정하는 방법을 보여드려요. 드라이 런 어노테이션을 사용하면 프로덕션 트래픽에 적용하기 전에 인가 정책의 효과를 더 잘 이해할 수 있어요. 이는 잘못된 인가 정책으로 프로덕션 트래픽이 깨지는 위험을 줄이는 데 도움을 줘요.
시작하기 전에 (Before you begin)
이 작업을 시작하기 전에 다음을 수행하세요.
- Istio 인가 개념을 읽으세요.
- Istio 설치 가이드를 따라 Istio를 설치하세요.
- 드라이 런 추적 결과를 확인하기 위해 Zipkin을 배포하세요. Zipkin 작업을 따라 클러스터에 Zipkin을 설치하세요.
- 드라이 런 메트릭 결과를 확인하기 위해 Prometheus를 배포하세요. Prometheus 작업을 따라 클러스터에 Prometheus를 설치하세요.
- 테스트 워크로드 배포하기: 이 작업은
foo네임스페이스에 배포된httpbin과curl두 워크로드를 사용해요. 두 워크로드 모두 Envoy 프록시 사이드카로 실행돼요. 다음 명령으로foo네임스페이스를 만들고 워크로드를 배포하세요.
$ kubectl create ns foo
$ kubectl label ns foo istio-injection=enabled
$ kubectl apply -f @samples/httpbin/httpbin.yaml@ -n foo
$ kubectl apply -f @samples/curl/curl.yaml@ -n foo
- 드라이 런 로깅 결과를 확인하기 위해 프록시 디버그 레벨 로그를 활성화하세요.
$ istioctl proxy-config log deploy/httpbin.foo --level "rbac:debug" | grep rbac
rbac: debug
- 다음 명령으로
curl이httpbin에 접근할 수 있는지 확인하세요.
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{http_code}\n"
200
[!note] 작업을 따르면서 예상 출력이 안 보이면 몇 초 후에 다시 시도하세요. 캐싱과 전파 오버헤드로 인해 지연이 발생할 수 있어요.
드라이 런 정책 만들기 (Create dry-run policy)
- 다음 명령으로 드라이 런 어노테이션
"istio.io/dry-run": "true"가 있는 인가 정책을 만드세요.
$ kubectl apply -n foo -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-path-headers
annotations:
"istio.io/dry-run": "true"
spec:
selector:
matchLabels:
app: httpbin
action: DENY
rules:
- to:
- operation:
paths: ["/headers"]
EOF
다음 명령을 사용해서 기존 인가 정책을 드라이 런 모드로 빠르게 변경할 수도 있어요.
$ kubectl annotate --overwrite authorizationpolicies deny-path-headers -n foo istio.io/dry-run='true'
- 정책이 드라이 런 모드로 생성됐으므로
/headers경로에 대한 요청이 허용되는지 확인하려면 다음 명령으로curl에서httpbin으로 20개의 요청을 보내세요. 요청에는 Zipkin 추적을 항상 트리거하는 헤더X-B3-Sampled: 1이 포함돼요.
$ for i in {1..20}; do kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl http://httpbin.foo:8000/headers -H "X-B3-Sampled: 1" -s -o /dev/null -w "%{http_code}\n"; done
200
200
200
...
프록시 로그에서 드라이 런 결과 확인하기
드라이 런 결과는 shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0] 형식의 프록시 디버그 로그에서 찾을 수 있어요. 다음 명령으로 로그를 확인하세요.
$ kubectl logs "$(kubectl -n foo -l app=httpbin get pods -o jsonpath={.items..metadata.name})" -c istio-proxy -n foo | grep "shadow denied"
2021-11-19T20:20:48.733099Z debug envoy rbac shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]
2021-11-19T20:21:45.502199Z debug envoy rbac shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]
2021-11-19T20:22:33.065348Z debug envoy rbac shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]
...
로깅에 대한 자세한 내용은 문제 해결 가이드도 참고하세요.
Prometheus를 사용해 메트릭에서 드라이 런 결과 확인하기
- 다음 명령으로 Prometheus 대시보드를 여세요.
$ istioctl dashboard prometheus
- Prometheus 대시보드에서 다음 메트릭을 검색하세요.
envoy_http_inbound_0_0_0_0_80_rbac{authz_dry_run_action="deny",authz_dry_run_result="denied"}
- 조회한 메트릭 결과를 다음과 같이 확인하세요.
envoy_http_inbound_0_0_0_0_80_rbac{app="httpbin",authz_dry_run_action="deny",authz_dry_run_result="denied",instance="10.44.1.11:15020",istio_io_rev="default",job="kubernetes-pods",kubernetes_namespace="foo",kubernetes_pod_name="httpbin-74fb669cc6-95qm8",pod_template_hash="74fb669cc6",security_istio_io_tlsMode="istio",service_istio_io_canonical_name="httpbin",service_istio_io_canonical_revision="v1",version="v1"} 20
- 조회한 메트릭의 값은
20이에요(보낸 요청 수에 따라 다른 값을 찾을 수도 있어요. 값이 0보다 크면 정상이에요). 이는 포트80의httpbin워크로드에 적용된 드라이 런 정책이 한 요청과 일치했음을 의미해요. 정책이 드라이 런 모드가 아니었다면 그 요청을 거부했을 거예요. - 다음은 Prometheus 대시보드의 스크린샷이에요.
Zipkin을 사용해 추적에서 드라이 런 결과 확인하기
- 다음 명령으로 Zipkin 대시보드를 여세요.
$ istioctl dashboard zipkin
curl에서httpbin으로의 요청에 대한 추적 결과를 찾으세요. Zipkin의 지연으로 인해 추적 결과가 안 보이면 요청을 몇 개 더 보내보세요.- 추적 결과에서 다음 커스텀 태그를 찾아
foo네임스페이스의 드라이 런 정책deny-path-headers에 의해 요청이 거부됐음을 나타내는지 확인하세요.
istio.authorization.dry_run.deny_policy.name: ns[foo]-policy[deny-path-headers]-rule[0]
istio.authorization.dry_run.deny_policy.result: denied
- 다음은 Zipkin 대시보드의 스크린샷이에요.
요약 (Summary)
프록시 디버그 로그, Prometheus 메트릭, Zipkin 추적 결과는 드라이 런 정책이 요청을 거부할 것임을 나타내요. 드라이 런 결과가 예상과 다르면 정책을 더 변경할 수 있어요. 드라이 런 정책을 추가로 유지해서 더 많은 프로덕션 트래픽으로 테스트하는 것이 권장돼요. 드라이 런 결과에 확신이 생기면 드라이 런 모드를 비활성화해서 정책이 실제로 요청을 거부하기 시작하게 할 수 있어요. 이는 다음 두 가지 방법 중 하나로 할 수 있어요.
- 드라이 런 어노테이션을 완전히 제거하거나
- 드라이 런 어노테이션의 값을
false로 변경하세요.
제한 사항 (Limitations)
드라이 런 어노테이션은 현재 실험 단계이며 다음 제한 사항이 있어요.
- 드라이 런 어노테이션은 현재 ALLOW와 DENY 정책만 지원해요.
- ALLOW와 DENY 정책이 프록시에서 별도로 시행되기 때문에 ALLOW와 DENY 정책 각각에 대해 두 개의 별도 드라이 런 결과(로그, 메트릭, 추적 태그)가 있어요. 요청이 ALLOW 정책에 의해 허용될 수 있지만 여전히 다른 DENY 정책에 의해 거부될 수 있으므로 두 드라이 런 결과를 모두 고려해야 해요.
- 프록시 로그, 메트릭, 추적의 드라이 런 결과는 수동 문제 해결 목적으로 사용되며, 사전 공지 없이 언제든 변경될 수 있으므로 API로 사용해서는 안 돼요.
정리 (Clean up)
- 구성에서
foo네임스페이스를 제거하세요.
$ kubectl delete namespace foo
- 더 이상 필요 없으면 Prometheus와 Zipkin을 제거하세요.
더 알아보기 (Learn more)
- 인가 정책의 동작과 시행 순서에 대해서는 인가 개념 문서를 참고하세요.
- 프록시 로그와 문제 해결에 대해서는 문제 해결 가이드를 참고하세요.