One of the ways a 서비스 메시로 인해 Kubernetes 환경 관리가 오히려 더 복잡해지는 경우 중 하나는 서비스 메시를 인그레스 컨트롤러와 별도로 구성해야 할 때입니다. 구성을 분리하면 단순히 시간이 많이 걸리는 데 그치지 않습니다. 적절한 트래픽 라우팅을 방해하는 구성 오류가 발생할 가능성이 커지고, 심지어 보안 취약점(예: 악의적인 사용자가 접근이 제한된 앱에 액세스하는 경우)과 좋지 않은 사용자 경험(예: 고객이 액세스 권한이 있는 앱을 이용하지 못하는 경우)으로 이어질 수도 있습니다. 별도로 구성하는 데 드는 시간뿐만 아니라 오류를 해결하는 데도 더 많은 시간을 쓰게 됩니다.
이러한 문제를 방지하고 시간을 절약하려면 NGINX Plus 기반 NGINX Ingress Controller를 NGINX Service Mesh와 통합하여 인그레스 및 이그레스 mTLS 트래픽을 모두 제어할 수 있습니다. 이 데모 영상에서는 전체 단계를 살펴봅니다.
관련 증빙 문서는 다음 섹션에 명시되어 있습니다:
- 사전 요구 사항
- NGINX Service Mesh와 함께 NGINX Ingress Controller 배포
- 표준 Kubernetes Ingress 리소스를 사용하여 앱 노출
- NGINX VirtualServer 리소스를 사용하여 앱 노출
- NGINX Ingress Controller를 사용하여 안전한 이그레스 경로 구성
사전 요구 사항 (0:18)
실제 데모를 시작하기 전에 다음과 같은 사전 준비를 완료했습니다:
- Kubernetes 클러스터에 NGINX Server Mesh 컨트롤 플레인을 설치하고, 서비스 메시를 위해 mTLS와
strict정책을 설정했습니다. - Installed NGINX Plus 기반 NGINX Ingress Controller를 Kubernetes 클러스터에 DaemonSet이 아닌 Deployment로 설치하고, 이그레스를 활성화했으며, exposed it as a service of type
LoadBalancer유형의 서비스로 노출했습니다.참고: 이 데모는 NGINX Open Source 기반 NGINX Ingress Controller에서는 작동하지 않습니다. 이 글의 나머지 부분에서는 가독성을 위해 NGINX Plus 기반 NGINX Ingress Controller를 간단히 “NGINX Ingress Controller”라고 부릅니다. - 당사의 지침에 따라 샘플
bookinfo앱을 다운로드하고 NGINX Service Mesh 사이드카를 삽입한 후 앱을 배포했습니다.
1단계에서 생성한 strict 정책으로 인해 메시 외부 클라이언트에서 bookinfo 앱으로 보내는 요청은 사이드카에서 거부됩니다. 데모에서는 먼저 다음 명령을 실행하여 포트 포워딩을 설정하는 방식으로 이를 보여 줍니다:
> kubectl port-forward svc/product-page 9080Forwarding from 127.0.0.1:9080 -> 9080
Forwarding from [::1]:9080 -> 9080
Handling connection for 9080앱에 액세스하려고 하면 상태 코드 503이 반환됩니다. 로컬 머신이 서비스 메시의 일부가 아니기 때문입니다:
> curl localhost:9080503NGINX Service Mesh와 함께 NGINX Ingress Controller 배포하기(1:50)
앱을 외부에 노출하는 과정의 첫 번째 단계는 NGINX Ingress Controller 인스턴스를 배포하는 것입니다. 관련 지침은 다음 튜토리얼에서 확인할 수 있습니다. Kubernetes용 NGINX Plus Ingress Controller로 배포하기.
NGINX는 이를 위해 Deployment 및 DaemonSet 매니페스트를 모두 제공합니다. 이 데모에서는 Deployment 매니페스트인 nginx-plus-ingress.yaml을 사용합니다. 이 매니페스트에는 인그레스 및 이그레스 트래픽을 모두 동일한 NGINX Ingress Controller 인스턴스를 통해 라우팅하기 위한 어노테이션이 포함되어 있습니다:
코드 예제를 로드하는 중…
이 매니페스트를 사용하면 NGINX Ingress Controller를 NGINX Service Mesh의 인증 기관(CA)인 Spire와 직접 통합할 수 있으므로 NGINX Ingress Controller에 NGINX Service Mesh 사이드카를 삽입할 필요가 없습니다. 대신 NGINX Ingress Controller는 메시의 Pod와 mTLS 통신을 수행하는 데 사용할 인증서와 키를 Spire CA에서 직접 가져옵니다. 이 매니페스트는 Spire 에이전트 주소를 지정합니다:
코드 예제를 로드하는 중…
그리고 Spire 에이전트 UNIX 소켓을 NGINX Ingress Controller 파드에 마운트합니다:
코드 예제를 로드하는 중…
매니페스트에서 마지막으로 주목할 점은 -enable-internal-routes CLI 인수입니다. 이 인수를 사용하면 이그레스 서비스로 라우팅할 수 있습니다:
코드 예제를 로드하는 중…
데모를 시작하기 전에 kubectl apply -f nginx-plus-ingress.yaml 명령을 실행하여 NGINX Ingress Controller를 설치했으며, 이제 nginx-ingress 네임스페이스의 배포를 살펴보겠습니다. 다음 출력의 READY 열에서 볼 수 있듯이 NGINX Ingress Controller Pod에는 컨테이너가 하나뿐입니다. 아직 NGINX Service Mesh 사이드카를 주입하지 않았기 때문입니다.
또한 NGINX Ingress Controller의 외부 IP 주소(여기서는 35.233.133.188)를 클러스터 외부에 노출하기 위해 LoadBalancer 유형의 서비스도 배포했습니다. 이 IP 주소를 통해 샘플 bookinfo 애플리케이션에 액세스하겠습니다.
> kubectl get pods --namespace=nginx-ingressNAME READY STATUS RESTARTS AGE
pod/nginx-ingress-867f954b8f0fzdrm 1/1 Running 0 3d3h
NAME TYPE CLUSTER-IP EXTERNAL-IP ...
service-nginx-ingress LoadBalancer 10.31.245.207 35.233.133.188 ...
... PORT(S) AGE
... 80:31469/TCP,443:32481/TCP 4d2h
...표준 Kubernetes Ingress 리소스를 사용하여 앱 외부에 노출하기 (3:55)
이제 bookinfo 앱을 메시에서 외부에 노출하기 위해 bookinfo-ingress.yaml에 정의된 표준 Kubernetes Ingress 리소스를 사용합니다. 관련 지침은 다음 튜토리얼에서 확인할 수 있습니다. NGINX Plus Ingress Controller를 사용하여 애플리케이션 노출하기.
코드 예제를 로드하는 중…
이 리소스는 10번째 줄에서 bookinfo 앱의 Kubernetes Secret을 참조하며, bookinfo.example.com에 대한 요청을 productpage 서비스로 전송하도록 지정하는 라우팅 규칙을 포함합니다(11~18번째 줄). 이 Secret은 bookinfo-secret.yaml에 정의되어 있습니다:
코드 예제를 로드하는 중…
다음 명령을 실행하여 키와 인증서를 로드합니다. 데모에서는 자체 서명된 인증서를 사용합니다:
> kubectl apply -f bookinfo-secret.yamlsecret/bookinfo-secret unchangedIngress 리소스를 활성화합니다:
> kubectl apply -f bookinfo-ingress.yamlingress.networking.k8s.io/bookinfo-ingress deleted그리고 출력 끝부분의 이벤트를 통해 Ingress Controller가 리소스에 정의된 경로를 추가했는지 확인합니다:
> kubectl describe ingress bookinfo-ingress...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal AddedOrUpdated 5s nginx-ingress-controller Configuration for ...
...default/bookinfo-ingress was added or updated이제 데모에서는 브라우저를 사용하여 bookinfo 앱의 https://bookinfo.example.com/에 접속합니다. (앞서 로컬 /etc/hosts 파일에 위에서 언급한 Ingress Controller 서비스의 IP 주소(데모에서는 35.233.133.188)와 bookinfo.example.com 간의 매핑을 추가했습니다. 자세한 방법은 설명서를 참조하세요.) 페이지의 도서 리뷰 섹션에 표시되는 정보는 요청이 bookinfo.yaml에 정의된 reviews 서비스의 세 가지 버전에 차례로 전달됨에 따라 주기적으로 변경됩니다(다운로드).
다음으로 클러스터로 유입되는 인그레스 트래픽을 검사합니다. generate-traffic.sh 스크립트를 실행하여 NGINX Ingress Controller의 공용 IP 주소를 통해 productpage 서비스에 요청을 보낸 다음, nginx-meshctl top 명령을 실행하여 트래픽을 모니터링합니다:
> nginxmesh-ctl top deploy/productpage-v1Deployment Direction Resource Success Rate P99 P90 P50 ...
productpage-v1
To details-v1 100.00% 3ms 3ms 2ms
To reviews-v2 100.00% 99ms 90ms 20ms
To reviews-v3 100.00% 99ms 85ms 18ms
To reviews-v1 100.00% 20ms 17ms 9ms
From nginx-ingress 100.00% 192ms 120ms 38ms
... NumRequests
... 14
... 5
... 5
... 12NGINX VirtualServer 리소스를 사용하여 앱 노출하기(6:45)
다음으로 NGINX VirtualServer 리소스를 사용하여 앱을 외부에 노출하는 또 다른 방법을 살펴보겠습니다. 이 리소스는 트래픽 분할 및 콘텐츠 기반 라우팅과 같은 더욱 복잡한 트래픽 처리를 지원하는 NGINX Ingress Controller의 사용자 지정 리소스입니다.
먼저 표준 Ingress 리소스를 삭제합니다:
> kubectl delete -f bookinfo-ingress.yamlingress.networking.k8s.io "bookinfo-ingress" deletedbookinfo-vs.yaml 파일은 bookinfo-ingress.yaml과 동일한 Secret을 사용하여 mTLS를 구성합니다(7~8행). 9~12행에서는 productpage 서비스를 업스트림으로 정의하고, 13~24행에서는 GET 방식으로 bookinfo.example.com에 전송된 모든 요청을 해당 업스트림으로 전달하는 경로를 정의합니다. GET 이외의 HTTP 메서드에는 상태 코드 405를 반환합니다.
코드 예제를 로드하는 중…
리소스를 적용합니다:
> kubectl apply -f bookinfo-vs.yamlvirtualserver.kubernetes.nginx.org/bookinfo-vs created그런 다음 Ingress 리소스에서와 동일한 단계를 수행합니다. 즉, kubectl describe 명령을 실행하여 올바르게 배포되었는지 확인하고 브라우저에서 앱에 접속합니다. 앱이 제대로 작동하고 있음을 확인하는 또 다른 방법은 POST 메서드를 거부하는지 확인하는 것입니다:
> curl -k -X POST https://bookinfo.example.com/Method not allowedNGINX Ingress Controller를 사용하여 보안 이그레스 경로 구성하기(8:44)
이제 송신 트래픽을 NGINX Ingress Controller를 통해 라우팅하는 방법을 살펴보겠습니다. 튜토리얼 NGINX Plus Ingress Controller로 안전한 송신 경로 구성하기에서는 다양한 샘플 앱을 사용하여 이 과정을 설명합니다.
간단한 bash Pod는 이미 bash.yaml에 정의했으며, 요청을 보내는 기본 네임스페이스에 배포했습니다. 이 출력의 READY 열에서 볼 수 있듯이 NGINX Service Mesh 사이드카가 주입되었습니다.
> kubectl get allNAME READY STATUS RESTARTS AGE
pod/bash-6ccb678958-zsgm7 2/2 Running 0 77s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.31.240.1 <none> 443/TCP 4d2h
...Pod 내부에서 이그레스 서비스로의 요청을 허용해야 하는 몇 가지 사용 사례가 있습니다. 이그레스 서비스란 NGINX Service Mesh에 속하지 않는 모든 엔터티를 의미합니다. 예를 들면 다음 위치에 배포된 서비스가 있습니다:
- 클러스터 외부
- 다른 클러스터에서
- 동일한 클러스터에 있지만 NGINX Service Mesh 사이드카가 삽입되지 않은 경우
이 데모에서는 마지막 사용 사례를 살펴봅니다. 애플리케이션은 legacy 네임스페이스에 배포되어 있으며, 이 네임스페이스는 NGINX Service Mesh의 제어를 받지 않고 NGINX Service Mesh 사이드카 자동 주입도 비활성화되어 있습니다. 이 애플리케이션에는 하나의 파드만 실행되고 있습니다.
> kubectl get all --namespaces=legacyNAME READY STATUS RESTARTS AGE
pod/target-5f7bcb96c6-km9lz 1/1 Running 0 27m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/target-svc ClusterIP 10.31.245.213 <none> 80/TCP,443/TCP 27m
...NGINX Service Mesh에 strict mTLS 정책을 구성했다는 점을 기억하세요. 따라서 bash Pod에서 대상 서비스로 직접 요청을 보낼 수 없습니다. 두 서비스가 서로 인증할 수 없기 때문입니다. 요청을 보내려고 하면 다음과 같이 상태 코드 503이 반환됩니다:
> kubectl exec -it bash-6ccb678958-zsgm7 -c bash -- curl target-svc.legacycurl: (56) Recv failure: connection reset by peer
503command terminated with exit code 56해결 방법은 bash 파드가 NGINX Ingress Controller를 통해 외부로 트래픽을 전송할 수 있도록 설정하는 것입니다. bash.yaml의 14~15번째 줄에 있는 주석을 해제합니다:
코드 예제를 로드하는 중…
그런 다음 새 구성을 적용합니다:
> kubectl apply -f bash.yamldeployment.apps/bash configured그리고 새 bash Pod가 실행되었는지 확인합니다:
> kubectl get podsNAME READY STATUS RESTARTS AGE
bash-678c8b4579-7sfml 2/2 Running 0 6s
bash-6ccb678958-zsgm7 2/2 Terminating 0 3m28s이제 이전과 동일한 kubectl exec 명령을 실행하여 bash 파드에서 대상 서비스로 요청을 보내면 상태 코드 503 대신 404가 반환됩니다. 이는 bash 파드가 NGINX Ingress Controller에 요청을 성공적으로 보냈지만, 정의된 경로가 없어 NGINX Ingress Controller가 요청을 어디로 전달해야 할지 알 수 없음을 의미합니다.
legacy-route.yaml에 다음 Ingress 리소스 정의를 사용하여 필요한 경로를 생성합니다. 7번째 줄의 internal-route 주석은 대상 서비스가 인터넷에 노출되지 않고 NGINX Service Mesh 내의 워크로드에만 노출됨을 의미합니다.
코드 예제를 로드하는 중…
새 리소스를 활성화하고 NGINX Ingress Controller가 리소스에 정의된 경로를 추가했는지 확인합니다:
> kubectl apply -f legacy-route.yamlingress.networking.k8s.io/target-internal-route created
> kubectl describe ingress target-internal-route -n legacy
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal AddedOrUpdated 6s nginx-ingress-controller Configuration for ...
...legacy/target-internal-route was added or updated이제 kubectl exec 명령어를 실행하면 대상 서비스에 연결됩니다:
{"req": {"method": "GET" "url": "/",
"host": "target-svc.legacy",
"remoteAddr": "10.28.2.76:56086"}}송신 트래픽을 NGINX Ingress Controller를 통해 라우팅하면 클러스터 내부에서 접근할 수 있는 외부 서비스를 정확하게 제어할 수 있다는 장점이 있습니다. 즉, 경로를 정의한 외부 서비스에만 접근할 수 있습니다.
마지막으로 데모에서는 송신 트래픽을 모니터링하는 방법을 보여 줍니다. 여러 요청을 보내기 위해 kubectl exec 명령을 실행한 다음, 다음 명령을 실행합니다:
> nginxmesh-ctl top deploy/nginx-ingress -n nginx-ingressDeployment Direction Resource Success Rate P99 P90 P50 NumRequests
nginx-ingress
To target 100.00% 1ms 1ms 1ms 9
From bash 100.00% 0ms 0ms 0ms 9지연 시간에 “No”라고 말하세요 – NGINX Ingress Controller와 함께 NGINX Service Mesh를 사용해 보세요
많은 서비스 메시가 인그레스 및 이그레스 게이트웨이 옵션을 제공하지만, NGINX 통합에는 지연 시간 단축이라는 또 하나의 장점이 있습니다. 대부분의 메시에서는 인그레스 컨트롤러에 사이드카를 삽입해야 하므로 트래픽이 애플리케이션으로 이동하는 도중에 한 단계를 더 거쳐야 합니다. 단 몇 초도 중요하며, 이러한 추가 단계로 인해 디지털 경험이 느려지면 고객이 다른 서비스를 선택할 수 있습니다. NGINX Service Mesh는 NGINX Ingress Controller에 사이드카를 삽입하지 않으므로 불필요한 지연 시간을 유발하지 않습니다. 대신 NGINX Ingress Controller는 메시의 CA인 Spire와 직접 통합되어 NGINX Service Mesh의 일부가 됩니다. NGINX Ingress Controller는 Spire 에이전트에서 인증서와 키를 가져와 메시가 적용된 Pod와의 mTLS 인증서 교환에 사용하기만 하면 됩니다.
Kubernetes용 NGINX Ingress Controller에는 NGINX Open Source와 NGINX Plus의 두 가지 버전이 있습니다. 이 블로그에서 설명한 대로 NGINX Service Mesh와 함께 NGINX Ingress Controller를 배포하려면 30일 무료 평가판으로 제공되는 NGINX Plus 버전을 사용해야 합니다.
NGINX Service Mesh는 완전히 무료이며 지금 바로 다운로드할 수 있고 10분 이내에 배포할 수 있습니다! 시작하려면 문서를 확인하고 GitHub를 통해 사용 경험을 알려주세요.
관련 블로그 게시물
시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.
F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.
Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.
진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.
NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.
Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.