[Kubernetes] Ingress & Ingress Controller
앞서 알아보았던 Service 중 외부 요청을 처리하기 위한 것에는 NodePort가 있었다.
NodePort는 클러스터 내의 모든 노드에 특정 포트를 오픈시켜 외부로부터 접근할 수 있도록 하는 서비스이다. 이러한 방식으로 클러스터 내부 네트워크로 접근하는 방식에는 사실 몇가지 애로사항이 존재한다.
- 포트 사용 문제
- NodePort는 각 서비스별로 하나의 포트를 고정으로 사용한다.
- NodePort 기본 정의에 따라 30000~32767 사이의 포트만 지정해줄 수 있다.
- SSL 인증서 사용 불가
이러한 애로사항을 해결해주기 위해 LoadBalancer 서비스를 사용할 수 있다.
하지만 LoadBalancer는 Public Cloud에 많이 의존하게 되는 것부터 노출시킬 서비스에 대해 각각 IP주소를 가진다는 점과노출시킬 서비스마다 LoadBalancer 비용이 증가하게 된다는 점이 존재했다.
결론적으로 NodePort와 LoadBalancer를 융합시킨 타입의 리소스가 등장하게 되는데, 바로 이번에 알아볼 Ingress이다.
Ingress
클러스터 외부에서 내부로 접근하는 요청 트래픽을 처리하기 위한 규칙들의 모음으로 Layer 7 라우팅의 기능을 제공한다.
Ingress는 대표적으로 아래와 같은 기능을 지원한다.
- 외부에서 접근가능한 URL
- 트래픽 로드밸런싱
- SSL 종단간 암호화
- 도메인 기반 가상호스팅
Ingress Controller
Ingress 규칙에 맞춰 라우팅 기능을 수행하는 Controller로 Ingress가 실제로 동작하기 위해 반드시 필요한 컴포넌트이다.
Public cloud 환경에서 Ingress Controller는 각 CSP 별로 제공해주는 로드밸런서를 Controller로 이용해서 연동시킬 수 있다.
반면 온프래미스와 같이 클러스터를 직접 구축한 경우에는 Ingress Controller를 별도로 올려서 연동해주어야한다. 대표적인 Ingress Controller에는 Nginx(ingress-nginx), HAProxy, Istio, Kong과 같은 것들이 있다.
이 중 Nginx Ingress Controller는 Kubernetes가 공식적으로 오픈소스 형태로 제공하고 있다.
Nginx Ingress Controller를 이용한 Ingress 구축
이번에는 클러스터에 Nginx Ingress Controller를 이용해 Ingress를 구축해보고 각 접근 유형별로 라우팅되도록 설정해보도록 한다.
- URI 기반 라우팅
- 호스트 기반 라우팅
테스트 클러스터 구축에는 WSL + Docker Desktop의 Kubernetes 엔진을 이용하였다.
먼저, Nginx Ingress Controller를 클러스터에 설치해주도록 한다.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yaml
해당 yaml을 적용하면 Nginx Ingress Controller 리소스가 배포된다.
ingress-nginx-controller pod가 정상적으로 Running되는 것을 확인 후, 라우팅 예시로 사용할 deployment와 service를 생성해준다.
URI 기반 라우팅
먼저 URI 기반 라우팅을 테스트해볼 service를 2개 생성해본다.
URI path 2종류(/auth, /post)로 요청이 오는 경우, 각 path 별로 지정된 Service로 트래픽이 흘러가게 구성해보도록 한다.
apiVersion: v1
kind: Service
metadata:
name: auth
spec:
type: NodePort
selector:
app: auth
ports:
- port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth
spec:
replicas: 2
selector:
matchLabels:
app: auth
template:
metadata:
labels:
app: auth
spec:
containers:
- name: simple-auth
image: httpd
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: post
spec:
type: NodePort
selector:
app: post
ports:
- port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: post
spec:
replicas: 2
selector:
matchLabels:
app: post
template:
metadata:
labels:
app: post
spec:
containers:
- name: simple-post
image: nginx
ports:
- containerPort: 80
Ingress로 연결해줄 Service들을 생성하고 Ingress 리소스를 작성하고 배포하도록 한다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
nginx.ingress.kubernetes.io/rewrite-target: / # redirect시킬 경로
nginx.ingress.kubernetes.io/ssl-redirect: "false" # HTTPS 강제 리다이렉트 미사용
spec:
ingressClassName: nginx # nginx Ingress Controller 사용 선언
rules: # ** Ingress의 규칙 선언 부 **
- host: my.simple-service.io # ingress에서 사용될 도메인 host
http:
paths:
- path: /auth # /auth 경로의 요청일 경우
pathType: Prefix
backend:
service:
name: auth # auth Service로 연결
port:
number: 80
- path: /post # /post 경로의 요청일 경우
pathType: Prefix
backend:
service:
name: post # post Service로 연결
port:
number: 80
WSL의 경우, /etc/hosts 파일의 수정이 필요하다.
본래 Ingress Controller는 LoadBalancer와 같이 Public IP가 연결된 External IP가 Address로 설정되는데, 이 예시에서는 간단하게 local로 Ingress Controller를 사용해보는 것이기 때문에
Ingress의 host로 설정해준 도메인 주소를 localhost에 매핑해준다.
# /etc/hosts
127.0.0.1 my.simple-service.io
Ubuntu 환경에서 hosts 파일을 수정한 뒤, 해당 도메인으로 요청을 전송하면 아래와 같이 각 path별로 매핑시켜준 Ingress Rule에 따라 서비스로 연결되는 것을 볼 수 있다.
my.simple-service.io/auth로 들어오는 요청은 Service 'auth' [httpd]로 전달되고,
my.simple-service.io/post로 들어오는 요청은 Service 'post' [nginx]로 전달되는 구조이다.
Host 기반 라우팅
다른 도메인으로 요청이 들어오는 경우에 각각 다른 Service로 연결되도록 설정해본다.
동일하게 2개의 Service를 올리되, Ingress의 Rule이 각 host에 따라 다른 백엔드를 갖도록 설정해준다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
nginx.ingress.kubernetes.io/rewrite-target: / # redirect시킬 경로
nginx.ingress.kubernetes.io/ssl-redirect: "false" # HTTPS 강제 리다이렉트 미사용
spec:
ingressClassName: nginx
rules:
- host: auth.simple-service.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: auth
port:
number: 80
- host: post.simple-service.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: post
port:
number: 80
hosts 파일내용도 변경해준 뒤, 각 서브도메인 별로 Ingress Rule로 매핑된 Service로 연결됨을 확인할 수 있다.
이렇게 Ingress와 Ingress Controller의 개념과 Nginx Ingress Controller를 간단하게 사용해보았다.
다음으로는 Public Cloud 환경들이 각각 제공해주는 로드밸런서 서비스를 연동해서 Ingress를 사용해보도록한다.