서비스 접근 제한하기
서비스 접근 제한하기 (Restricting Access To Services)
Emojivoto 예제로 Linkerd의 정책 리소스(Server, ServerAuthorization)를 사용해 특정 서비스에 접근할 수 있는 클라이언트를 제한하는 방법을 알려드려요.
본문
Linkerd 정책 리소스는 어떤 클라이언트가 서비스에 접근할 수 있는지 제한하는 데 사용할 수 있습니다. 이 예시에서는 Emojivoto를 사용해 Voting 서비스에 대한 접근을 Web 서비스에서만 호출되도록 제한하는 방법을 보여드릴게요.
정책 리소스에 대한 더 포괄적인 설명은 정책 레퍼런스 문서(Policy reference docs)를 참고하세요.
사전 준비
클러스터에 Linkerd와 그 Viz 확장을 설치해야 합니다. 아직 안 했다면 Linkerd 설치 가이드를 따르세요.
설정 (Setup)
Emojivoto 애플리케이션을 주입하고 설치합니다:
`$ linkerd inject https://run.linkerd.io/emojivoto.yml | kubectl apply -f -
...
$ linkerd check -n emojivoto --proxy -o short
...
`
Server 리소스 만들기
Voting 서비스용 Server 리소스를 만드는 것으로 시작합니다. Server는 워크로드의 특정 포트를 설명하는 Linkerd 커스텀 리소스예요. Server 리소스를 만들고 나면, 인가된 클라이언트만 접근할 수 있습니다(곧 클라이언트를 인가하는 방법을 볼 거예요).
`kubectl apply -f - ---
apiVersion: policy.linkerd.io/v1beta1
kind: Server
metadata:
namespace: emojivoto
name: voting-grpc
labels:
app: voting-svc
spec:
podSelector:
matchLabels:
app: voting-svc
port: grpc
proxyProtocol: gRPC
EOF
`
이 Server가 podSelector로 자신이 설명하는 pod(여기서는 voting 서비스 pod)를 선택하는 것을 볼 수 있어요. 또한 적용되는 이름 있는 포트(grpc)를 지정합니다. 마지막으로 이 포트에서 서비스되는 프로토콜을 지정하죠. 이것은 프록시가 트래픽을 올바르게 다루고 프로토콜 감지를 건너뛸 수 있게 해줍니다.
이 시점에서 어떤 클라이언트도 이 서비스에 인가되지 않았으므로, Web 서비스에서 Voting으로 가는 요청이 거부되기 시작하면서 성공률이 떨어지는 것을 볼 수 있을 거예요.
linkerd viz authz 명령으로 voting 서비스로 오는 요청의 인가 상태를 확인하고, voting-grpc 서버로 들어오는 모든 요청이 현재 인가되지 않았음을 볼 수 있어요:
`> linkerd viz authz -n emojivoto deploy/voting
ROUTE SERVER AUTHORIZATION UNAUTHORIZED SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
default default:all-unauthenticated default/all-unauthenticated 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
probe default:all-unauthenticated default/probe 0.0rps 100.00% 0.2rps 1ms 1ms 1ms
default voting-grpc 1.0rps 0.00% 0.0rps 0ms 0ms 0ms
`
ServerAuthorization 리소스 만들기
ServerAuthorization는 일련의 클라이언트에게 일련의 Server에 대한 접근 권한을 부여합니다. 여기서는 위에서 만든 Voting Server에 Web 서비스 접근을 부여하는 ServerAuthorization을 만들 거예요. meshed mTLS는 아이덴티티의 기반으로 ServiceAccounts를 사용하므로, 우리의 인가도 ServiceAccounts 기반이 됩니다.
`kubectl apply -f - ---
apiVersion: policy.linkerd.io/v1beta1
kind: ServerAuthorization
metadata:
namespace: emojivoto
name: voting-grpc
labels:
app.kubernetes.io/part-of: emojivoto
app.kubernetes.io/name: voting
app.kubernetes.io/version: v11
spec:
server:
name: voting-grpc
# The voting service only allows requests from the web service.
client:
meshTLS:
serviceAccounts:
- name: web
EOF
`
이제 Voting 서비스로 가는 모든 요청이 voting-grpc ServerAuthorization에 의해 인가되는 것을 볼 수 있습니다. linkerd viz auth 명령은 시간 창에 걸쳐 질의하므로 잠깐 동안 UNAUTHORIZED 요청이 표시될 수 있다는 점을 알아두세요.
`> linkerd viz authz -n emojivoto deploy/voting
ROUTE SERVER AUTHORIZATION UNAUTHORIZED SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
default default:all-unauthenticated default/all-unauthenticated 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
probe default:all-unauthenticated default/probe 0.0rps 100.00% 0.2rps 1ms 1ms 1ms
default voting-grpc serverauthorization/voting-grpc 0.0rps 83.87% 1.0rps 1ms 1ms 1ms
`
또한 다른 pod의 요청이 거부되는 것을 grpcurl pod를 만들어 그것에서 Voting 서비스에 접근을 시도해 테스트할 수 있어요:
`> kubectl run grpcurl --rm -it --image=networld/grpcurl --restart=Never --command -- ./grpcurl -plaintext voting-svc.emojivoto:8080 emojivoto.v1.VotingService/VoteDog
Error invoking method "emojivoto.v1.VotingService/VoteDog": failed to query for service descriptor "emojivoto.v1.VotingService": rpc error: code = PermissionDenied desc =
pod "grpcurl" deleted
pod default/grpcurl terminated (Error)
`
이 클라이언트는 인가되지 않았으므로, 이 요청은 PermissionDenied 오류로 거부됩니다.
여러 다른 클라이언트를 인가하려면 원하는 만큼 ServerAuthorization 리소스를 만들 수 있어요. 또한 인증되지 않은(즉 meshed되지 않은) 클라이언트를 인가할지, 인증된 임의의 클라이언트를 인가할지, 아니면 특정 아이덴티티를 가진 인증된 클라이언트만 인가할지 지정할 수 있습니다. 자세한 내용은 정책 레퍼런스 문서를 참고하세요.
기본 정책 설정하기
클러스터를 더 잠그려면 Server 리소스가 정의되지 않은 모든 포트에 적용될 기본 정책을 설정할 수 있어요. Linkerd는 요청을 허용할지 결정할 때 다음 논리를 사용합니다:
- 포트에 Server 리소스가 있고 클라이언트가 그에 대한 ServerAuthorization 리소스와 일치하면: ALLOW
- 포트에 Server 리소스가 있지만 클라이언트가 그에 대한 어떤 ServerAuthorization과도 일치하지 않으면: DENY
- 포트에 Server 리소스가 없으면: 기본 정책 사용
linkerd upgrade 명령으로 기본 정책을 deny로 설정할 수 있어요:
`> linkerd upgrade --default-inbound-policy deny | kubectl apply -f -
`
또는 config.linkerd.io/default-inbound-policy 주석을 설정해 개별 워크로드나 네임스페이스에 기본 정책을 설정할 수 있습니다. 자세한 내용은 정책 레퍼런스 문서를 참고하세요.
포트에 Server가 정의되지 않으면 Linkerd는 readiness·liveness 프로브를 허용하는 기본 Server를 자동으로 사용합니다. 하지만 프로브를 처리하는 포트에 Server 리소스를 만들면, 그 프로브 요청을 허용하는 인가를 명시적으로 만들어야 합니다. 라우트 범위 인가를 추가하는 방법에 대한 자세한 내용은 라우트별 정책 구성(Configuring Per-Route Policy)을 참고하세요.
운영 중인 시스템에서 인가 정책 활성화하기
Server 리소스를 만든 뒤 ServerAuthorization을 만들기 전 사이에 모든 요청이 거부되던 시간이 있었음을 눈치챘을 거예요. 운영 중인 시스템에서 이런 상황을 피하려면 Server 리소스에서 감사 모드(audit mode)를 켠 채로 시작할 것을 권장합니다. 이 모드에서는 정책을 위반하는 트래픽이 실제로 거부되지 않고, 감사 모드를 끄면 어떤 일이 일어날지의 전체 그림을 대상 서비스의 프록시 로그/메트릭으로 확인할 수 있어요. 정책 규칙이 확실해지면 감사 모드를 제거해 정책을 완전히 시행할 수 있습니다.
라우트별 정책 (Per-Route Policy)
서비스 수준 인가 정책 외에도 개별 HTTP 라우트에 대해 인가 정책을 구성할 수 있습니다. 라우트별 정책에 대한 자세한 내용은 라우트별 정책 구성 문서를 참고하세요.
더 알아보기 (Learn more)
- 정책 레퍼런스 문서 (Policy reference)
- 라우트별 정책 구성 (Configuring Per-Route Policy)