본문 바로가기

쿠버네티스

쿠버네티스 인그레스(Ingress) 생성 + SSL/TLS 보안 연결

3개의 디플로이먼트에서 애플리케이션이 각각 생성되어 있다고 가정해보자

디플로이먼트들을 외부로 노출하려면 앞서배웠던 NodePort나 LoadBalancer타입의 서비스 3개를 생성해야 한다.

하지만 이 방법은 서비스마다 세부적인 설정(SSL/TLS 보안 연결, 접근 도메인 및 클라이언트 상태에 기반한 라우팅 등)을 할 때 추가적인 복잡성이 발생하게 되어 좋은 방법은 아니다.

인그레스 오브젝트를 사용하면 URL 엔드포인트를 단 하나만 생성함으로써 이러한 번거로움을 해결할 수 있다. 즉 3개의 서비스에 대해 3개의 URL이 각각 존재하는 것이 아닌, 인그레스에 접근하기 위한 단 하나의 URL만 존재한다. 따라서 클라이언트는 인그레스의 URI로만 접근하게 되며, 해당 요청은 인그레스에서 정의한 규칙에 따라 처리된 뒤 적절한 디플로이먼트의 포드로 전달된다.

이 과정에서 중요한 점은 라우팅 정의나 보안 연결 등과 같은 세부 설정은 서비스와 디플로이먼트가 아닌 인그레스에 의해 수행된다는 것이다. 각 디플로이먼트에 대해 일일이 설정을 적용할 필요 없이 하나의 설정 지점에서 처리 규칙을 정의하기만 하면 된다.

 

 

 

인그레스 생성을 위한 YAML파일(ingress-example.yaml) 작성

 

인그레스 생성 및 확인

# kubectl apply -f ingress-example.yaml
kubectl get ingress

인그레스는 요청을 처리하는 규칙을 정의하는 선언적인 오브젝트일 뿐, 외부 요청을 받아들일 수 있는 실제 서버가 아니기 때문에 인그레스 컨트롤러(Ingress Controller)라고 하는 특수한 서버에 적용해야 이 규칙을 사용할 수 있다. 즉, 실제로 외부 요청을 받아들이는 것은 인그레스 컨트롤러 서버이며, 이 서버가 인그레스 규칙을 로드해 사용한다.

 

 

Nginx 웹 서버 인그레스 컨트롤러 설치

# kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.35.0/deploy/static/provider/aws/deploy.yaml

 

 

"ingress-nginx" 네임스페이스로 생성된 포드, 디플로이먼트 확인

ingress-nginx 네임스페이스의 디플로이먼트와 포드를 확인해보면 Nginx 웹 서버가 생성되어 있을 것이다

# kubectl get pods,deploy -n ingress-nginx

 

 

인그레스 컨트롤러에 접근하기 위한 LoadBalancer 타입의 서비스가 자동으로 생성되었고, DNS 이름을 할당하여 사용할 수 있다

 

 

클라우드 환경인 경우 인그레스 테스트를 하기 위해서 LoadBalancer를 통해 Nginx 인그레스 컨트롤러에 접근하면 되지만, 가상머신처럼 클라우드 환경이 아닌 경우 각 노드의 랜덤한 포트로 Nginx 인그레스 컨트롤러에 접근할 수 있도록 NodePort 타입의 서비스를 생성한다

 

 

NodePort 타입의 서비스 생성을 위한 YAML파일(ingress-nginx-svc-nodeport.yaml) 작성

 

 

NodePort 타입의 서비스 생성 및 확인

# kubectl apply -f ingress-nginx-svc-nodeport.yaml
# kubectl get svc -n ingress-nginx

 

 

이제 인그레스, Nginx 인그레스 컨트롤러 및 Nginx 포드에 접근하기 위한 서비스의 준비가 완료되었다. 하지만 아직 인그레스의 종착점이 될 테스트용 디플로이먼트와 서비스를 생성하지 않았으므로 이를 생성해 최종적으로 인그레스의 동작 여부를 확인해보자

 

 

테스트용 디플로이먼트 생성을 위한 YAML파일(hostname-deployment.yaml) 작성

 

 

테스트용 서비스 생성을 위한 YAML파일(hostname-service.yaml) 작성

 

 

테스트용 디플로이먼트와 서비스 생성 및 확인

Nginx 인그레스 컨트롤러로 들어오는 요청은 이 디플로이먼트의 포드들로 분산될 것이다

# kubectl apply -f hostname-deployment.yaml
# kubectl get pods,deploy,svc

 

 

Nginx 인그레스 컨트롤러의 /echo-hostname으로 요청 전송

# curl 10.108.111.116/echo-host

"404 Not Found"에러가 뜨는 이유는 앞서 인그레스(ingress-example.yaml)를 생성할 때 Nginx 인그레스 컨트롤러에 alicek106.example.com으로 접근했을 때만 응답을 처리하도록 설정했기 때문이다. 따라서 alicek106.example.com이 아닌 다른 도메인 이름으로 접근할 때는 Nginx  인그레스 컨트롤러가 해당 요청을 처리하지 않는다

 

 

curl 명령어의 --resolve 옵션을 통해 임시로 도메인명 설정

# curl --resolve alicek106.example.com:80:10.108.111.116 alicek106.example.com/echo-hostname

정상적으로 요청을 처리한 것을 확인할 수 있다

 

 

Nginx 인그레스 컨트롤러는 인증서를 통한 보안 연결 기능을 제공한다. 쿠버네티스 뒤쪽에 있는 디플로이먼트와 서비스가 아닌, 앞쪽에 있는 인그레스 컨트롤러에 인증서를 적용해두면 요청이 전달되는 애플리케이션에 대해 모두 인증서 처리를 할 수 있다

 

 

보안 연결에 사용할 인증서와 비밀키 생성

(호스트명 앞에 있는 문자는 대문자 O)

# openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt -subj "/CN=<퍼블릭 DNS이름>/O=<호스트명>"

tls.key(비밀키)와 tls.crt(인증서)가 생성되었을 것이다. 이 파일들을 통해 tls타입의 시크릿을 생성해보자

 

 

TLS타입의 시크릿 생성

# kubectl create secret tls tls-secret --key tls.key --cert tls.crt
# kubectl describe secret tls-secret

 

 

인그레스 설정 추가

ingress-example.yaml(처음 인그레스 생성 때 사용했던) 파일을 열어서 spec.tls 내용을 추가하고 생성한다

# kubectl apply -f ingress-example.yaml

 

 

HTTPS로 접속

# curl https://jhb.example.com/echo-hostname -k

HTTPS로 접근했을 때에도 정상적으로 데이터를 반환하는 것을 확인할 수 있다

(인증서를 통해 보안 연결을 설정했을 때는 HTTP로 접근해도 자동으로 HTTPS로 리다이렉트된다)