NGINX Service Mesh mTLS 아키텍처
이 포스트에서는 NGINX Service Mesh 에서 mTLS를 구현하는 방법에 대한 개요를 제공합니다.
우리가 소유한 가장 가치 있는 것 중 하나는 데이터입니다. 해커는 이 사실을 알고 있고 이를 위해 무엇이든 할 것이며, 그들이 사용하는 자동화된 공격은 그 어느 때보다 쉽게 해커를 만듭니다. 한 번은 라즈베리파이(Raspberry Pi)의 SSH 포트를 인터넷에 열어두는 실수를 저질렀습니다. 몇 달 후 로그를 살펴보니 여러 IP 주소가 무차별 암호 대입 공격(Brute Force) 스크립트로 로그를 망치고 있는 것을 발견했습니다. 즉시 포트를 닫고 로그를 더 자주 확인하도록 메모했습니다. 라즈베리파이에 대한 침해가 해커들에게 많은 것을 가져다주지는 못했지만, 회사나 정부의 데이터 유출은 수십 억원의 비용이 들 수 있고 수년간 지속되는 영향을 미칠 수 있습니다.
Microservices와 Kubernetes를 채택함에 따라 잠재적인 공격 표면도 열어둡니다. Microservices 간의 서비스 간 통신은 메모리에서 모든 통신을 수행하는 Monoliths에 비해 더 많은 데이터를 제공합니다. 통신 서비스가 방화벽 뒤에 있더라도 유선 상의 일반 텍스트 데이터는 모니터링의 주요 사항입니다.
NGINX Service Mesh 를 채택하는 가장 큰 이유 중 하나는 서비스 간 트래픽을 관리하기 위해서입니다. 사이드카와 Control Plane의 조합을 통해 상호 TLS(mTLS)와의 연결 양쪽 끝을 중앙 집중식으로 관리하고 제어하여 유선 데이터를 암호화하고 인증할 수 있습니다. mTLS는 클라이언트와 서버가 인증서를 제시하고 서로를 인증하도록 하여 표준 TLS를 확장합니다. Service Mesh를 사용하면 mTLS를 “zero‑touch” 방식으로 구현할 수 있습니다. 즉, 개발자가 인증서로 애플리케이션을 개조하거나 상호 인증이 진행되고 있다는 사실을 알 필요가 없습니다.
목차
1. 개요
2. NGINX Service Mesh의 인증서 Lifecycle
2-1. Creation
2-2. Distribution
2-3. Enforcement
2-4. Rotation
3. Public Key Infrastructure(PKI)
4. 결론
5. 부록
5-1. Bootstrapping
5-2. Selectors
5-3. Pod Attestation
1. 개요
NGINX Service Mesh 는 Open Source SPIRE 소프트웨어를 중앙 인증 기관(Central Certificate Authority, CA)으로 사용합니다. SPIRE는 인증서의 전체 수명 주기(생성, 배포 및 순환)를 처리합니다. Service Mesh 내에서 NGINX Plus는 SPIRE 발급 인증서를 사용하여 mTLS 세션을 설정하고 트래픽을 암호화합니다.

다이어그램의 주요 구성 요소는 다음과 같습니다.
- SPIRE Server – SPIRE 서버는 Kubernetes StatefulSet로 실행됩니다. 실제 spire-server와 k8s-workload-registrar라는 두 개의 컨테이너로 구성됩니다.
- spire-server – NGINX Service Mesh mTLS 아키텍처의 핵심인 spire-server는 Workload에 대한 인증서를 발급하고 이를 Spire 에이전트에 Push 하는 CA입니다(아래 참조). Mesh의 모든 서비스에 대한 root CA이거나 신뢰 체인의 중간 CA 일 수 있습니다.
- k8s-workload-registrar – 유닉스 소켓을 통해. k8s-workload-registrar 컨테이너는 Kubernetes 사용자 정의 리소스(Custom Resource Definition, CRD)를 기반으로 합니다.
- Spire Agent – Kubernetes DaemonSet로 실행됩니다. 즉, 노드당 하나의 복사본이 실행됩니다. SPIRE 에이전트에는 두 가지 주요 기능이 있습니다.
- SPIRE 서버에서 인증서를 받아 캐시에 저장합니다.
- 나타나는 각 Pod를 “Attestation”합니다. 즉, UID, Name 및 Namespace를 포함하여 Pod에 대한 정보를 제공하도록 Kubernetes 시스템에 요청한 다음 해당 인증서를 조회하는 데 사용합니다.
- NGINX Plus Sidecar – SPIRE에서 생성 및 배포한 인증서를 사용하고 전체 mTLS Workflow를 처리하여 인증서를 교환 및 확인합니다.
2. NGINX Service Mesh의 인증서 Lifecycle
NGINX Service Mesh 의 mTLS 아키텍처의 주요 구성 요소에 대한 이해를 통해 이들이 어떻게 함께 작동하여 자체 포함 mTLS 시스템을 구축하는지 살펴볼 준비가 되었습니다.
2-1. Creation
mTLS Workflow의 첫 번째 단계는 실제 인증서를 만드는 것입니다. NGINX Service Mesh 에서 Kubernetes Pod를 배포할 때 어떤 일이 일어나는지 살펴보겠습니다:
- Pod가 배포됩니다.
- NGINX Service Mesh Control Plane은 mutating webhook를 사용하여 사이드카를 Pod 사양에 주입합니다.
- “pod created” 이벤트 알림에 대한 응답으로
k8s-workload-registrar
는 ServiceAccount 이름과 같이 인증서를 만드는 데 필요한 정보를 수집합니다. k8s-workload-registrar
는 Pod에 대한 인증서를 요청하기 위해 Unix 소켓을 통해spire-server
에 대한 API 호출을 수행합니다.spire-server
는 Pod에 대한 인증서를 생성합니다.
2-2. Distribution
새 인증서를 올바른 Pod에 안전하게 배포해야 합니다:
- SPIRE 에이전트는 새 인증서를 가져와 캐시에 저장합니다. SPIRE 에이전트와 서버는 gRPC를 사용하여 부트스트래핑(Bootstrapping)에 자세히 설명되어 있습니다.
- 주입된 Pod가 올라오고, NGINX Plus 사이드카가 주입됩니다.
- 사이드카는 Unix 소켓을 통해 동일한 노드에서 실행 중인 SPIRE 에이전트에 연결됩니다.
- SPIRE 에이전트는 Pod를 증명하고 올바른 인증서를 수집한 다음 Unix 소켓을 통해 사이드카로 보냅니다(자세한 내용은 Pod Attestation 참조).
2-3. Enforcement
NGINX Plus는 이제 인증서에 액세스할 수 있으며 이를 사용하여 mTLS를 수행할 수 있습니다. SPIRE에서 발급한 인증서가 있는 서버에 Pod가 연결하려고 할 때 어떻게 사용되는지 단계별로 살펴보겠습니다.
- Pod에서 실행 중인 애플리케이션이 서비스에 대한 연결을 시작합니다.
- NGINX Plus 사이드카는 iptables NAT 리다이렉션을 사용하여 연결을 가로챕니다.
- NGINX Plus는 대상 서비스의 사이드카에 대한 TLS 연결을 시작합니다.
- 서버 측 NGINX Plus는 클라이언트의 인증서 요청과 함께 인증서를 클라이언트로 보냅니다.
- 클라이언트 NGINX Plus는 trust root까지 서버 인증서의 유효성을 검사하고 자체 인증서를 서버로 보냅니다.
- 서버는 trust root까지 클라이언트 인증서의 유효성을 검사합니다.
- 상호 인증된 양쪽 모두 이제 표준 TLS Key 교환을 수행할 수 있습니다.
2-4. Rotation
원활한 트래픽 흐름을 유지하려면 만료 날짜 전에 인증서를 교체해야 합니다. 인증서 만료가 가까워지면 spire-server
는 새 인증서를 발급하고 순환 프로세스를 트리거(Triggers) 합니다. 새 인증서는 SPIR 에이전트에 Push되어 유닉스 소켓을 통해 NGINX Plus 사이드카에 Push됩니다.
3. Public Key Infrastructure(PKI)
SPIRE는 NGINX Service Mesh 배포의 trust root이거나 기존 Public Key Infrastructure(PKI)에 연결할 수 있습니다. 자세한 내용은 NGINX Service Mesh 설명서에서 upstream root CA를 사용하여 배포를 참조하십시오.
4. 결론
Monolith의 메모리에서 발생하는 대부분의 통신은 대신 Microservices 애플리케이션을 통해 Wire Expose 됩니다. 공격자가 이 데이터를 스누핑(Snooping)하지 못하도록 하려면 데이터를 암호화해야 합니다. NGINX Service Mesh 는 서비스를 수정할 필요 없이 서비스 간 통신을 암호화하는 Zero‑Touch mTLS 아키텍처를 제공합니다. NGINX Service Mesh 를 시작하려면 NGINX Service Mesh 소개 포스트를 참조하세요.
5. 부록
5-1. Bootstrapping
SPIRE 서버와 에이전트는 SSL/TLS를 사용하여 통신하므로 인증서 생성 및 배포를 담당하는 서비스 간에 보안 통신을 설정하기 위해 인증서를 사용하는 방법에 대한 질문이 제기됩니다. SPIRE 서버는 k8sbundle이라는 알림 플러그인으로 이를 수행합니다.
SPIRE 서버가 부팅되면 최신 root CA 인증서를 Kubernetes ConfigMap 리소스로 Push 합니다. ConfigMap은 SPIRE 에이전트가 수행한 것처럼 Pod가 파일 볼륨으로 마운트 할 수 있는 데이터를 저장하는 데 사용됩니다. SPIRE 에이전트가 부팅되면 root CA 인증서를 찾고 이를 사용하여 SPIRE 서버가 제시한 인증서를 검증합니다.
SPIRE 서버는 노드 Attestation 프로세스를 사용하여 SPIRE 에이전트를 검증합니다.
5-2. Selectors
Pod에서 특정 인증서를 발급하려면 Selectors라는 속성 집합이 있어야 합니다. SPIRE에서 발급한 각 인증서는 자신이 속한 Pod를 식별하는 Selectors 집합과 연결됩니다. NGINX Service Mesh 는 Pod UID를 사용하여 Pod를 고유하게 식별합니다. Pod가 나타난 후 Pod Attestation 중에 SPIRE 에이전트는 UID를 Selectors를 사용하여 Pod의 고유한 인증서를 조회합니다.
5-3. Pod Attestation
Attestation은 올바른 Pod에 인증서를 배포하는 프로세스의 한 단계(배포의 4단계) 일뿐이지만 전체 mTLS 아키텍처의 핵심 부분입니다. Attestation은 SPIRE 에이전트가 Pod에 대해 사용 가능한 모든 정보를 Kubernetes에 요청하는 것을 의미합니다. SPIRE 에이전트 로그의 Snippet은 Pod에서 수집한 정보를 보여줍니다.
"PID attested to have selectors" pid=1226861 selectors="[type:\"unix\" value:\"uid:2102\" type:\"unix\" value:\"gid:1000\" type:\"k8s\" value:\"sa:bookinfo-productpage\" type:\"k8s\" value:\"ns:default\" type:\"k8s\" value:\"pod-uid:5beeffac-756e-11ea-91e1-42010a8a008f\" type:\"k8s\" value:\"pod-name:productpage-v1-c7765c886-fvqqj\" type:\"k8s\" value:\"container-name:proxy\" type:\"k8s\" value:\"pod-label:spire-workload:productpage-v1\" type:\"k8s\" value:\"pod-label:version:v1\" type:\"k8s\" value:\"pod-label:app:productpage\" ]"
예를 들어 여기에서 SPIRE 에이전트는 Pod의 UID(pod‑uid, 여기서는 5b33…008f), Namespace(ns, 여기서는 기본값) 및 ServiceAccount(sa, 여기서는 bookinfo‑productpage)를 수집합니다. 그런 다음 Pod에 발급할 올바른 인증서를 찾기 위한 Selectors가 됩니다. 자세한 내용은 SPIRE 설명서의 Workload Attestation을 참조하십시오.
NGINX Serivce Mesh를 테스트 및 사용해 보려면 지금 30일 무료 평가판을 신청하거나 사용 사례에 대해 최신 소식을 빠르게 전달받고 싶으시면 아래 뉴스레터를 구독하세요.
댓글을 달려면 로그인해야 합니다.