# Ingress
⚡️ 목표
도메인을 이용하여 서로 다른 서비스에 접근하는 방법을 알아봅니다.
하나의 클러스터에서 여러 가지 서비스를 운영한다면 외부 연결을 어떻게 할까요? NodePort를 이용하면 서비스 개수만큼 포트를 오픈하고 사용자에게 어떤 포트인지 알려줘야 합니다. 그럴순 없죠!
위 샘플은 example.com
, subicura.com/blog
, subicura.com/help
주소로 서로 다른 서비스에 접근하는 모습입니다. 80(http)
또는 443(https)
포트로 여러 개의 서비스를 연결해야 하는데 이럴 때 Ingress
를 사용합니다.
# Ingress 만들기
echo 웹 애플리케이션을 버전별로 도메인을 다르게 만들어 보겠습니다.
minikube ip
로 테스트 클러스터의 노드 IP를 구하고 도메인 주소로 사용합니다. 결과 IP가 192.168.64.5
라면 사용할 도메인은 다음과 같습니다.
TIP
도메인을 테스트하려면 여러가지 설정이 필요합니다. 여기서는 별도의 설정없이 IP주소를 도메인에 넣어 바로 사용할 수 있는 sslip.io (opens new window) 서비스를 이용합니다.
# minikube에 Ingress 활성화하기
Ingress는 Pod, ReplicaSet, Deployment, Service와 달리 별도의 컨트롤러를 설치해야 합니다. 여러 가지 컨트롤러 중에 입맛에 맞게 고를 수 있는데 여기서는 nginx ingress controller를 사용합니다.
Ingress Controller
nginx를 제외한 대표적인 컨트롤러로 haproxy, traefik, alb등이 있습니다.
minikube addons enable ingress
# ingress 컨트롤러 확인
kubectl -n ingress-nginx get pod
실행 결과
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-n2684 0/1 Completed 0 96s
ingress-nginx-admission-patch-thq42 0/1 Completed 1 96s
ingress-nginx-controller-6d5f55986b-jkcfs 1/1 Running 0 96s
잘 설정 되었는지 확인합니다.
curl -I http://192.168.64.5/healthz # minikube ip를 입력
Docker
Docker driver를 사용중이라면 minikube service ingress-nginx-controller -n ingress-nginx --url
명령어를 이용하여 접속 주소를 확인합니다.
🏃 Starting tunnel for service ingress-nginx-controller.
|---------------|--------------------------|-------------|------------------------|
| NAMESPACE | NAME | TARGET PORT | URL |
|---------------|--------------------------|-------------|------------------------|
| ingress-nginx | ingress-nginx-controller | | http://127.0.0.1:51728 |
| | | | http://127.0.0.1:51729 |
|---------------|--------------------------|-------------|------------------------|
http://127.0.0.1:51728
http://127.0.0.1:51729
다음과 같이 출력된다면 첫번째 항목을 테스트 주소로 사용합니다. curl -I http://127.0.0.1:51728/healthz
실행 결과
HTTP/1.1 200 OK
Date: Sat, 05 Dec 2020 13:53:37 GMT
Content-Type: text/html
Content-Length: 0
Connection: keep-alive
# echo 웹 애플리케이션 배포
Nginx Ingress Controller 설치가 완료되면 echo 웹 애플리케이션을 배포합니다. v1, v2 2가지를 배포합니다.
Ingress Spec중에 rules.host
부분을 minikube ip
로 변경해야 합니다.
Docker
Docker driver를 사용중이라면 rules.host
부분에 127.0.0.1
을 사용합니다. v1.echo.127.0.0.1.sslip.io
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echo-v1
spec:
rules:
- host: v1.echo.192.168.64.5.sslip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: echo-v1
port:
number: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-v1
spec:
replicas: 3
selector:
matchLabels:
app: echo
tier: app
version: v1
template:
metadata:
labels:
app: echo
tier: app
version: v1
spec:
containers:
- name: echo
image: ghcr.io/subicura/echo:v1
livenessProbe:
httpGet:
path: /
port: 3000
---
apiVersion: v1
kind: Service
metadata:
name: echo-v1
spec:
ports:
- port: 3000
protocol: TCP
selector:
app: echo
tier: app
version: v1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echo-v2
spec:
rules:
- host: v2.echo.192.168.64.5.sslip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: echo-v2
port:
number: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-v2
spec:
replicas: 3
selector:
matchLabels:
app: echo
tier: app
version: v2
template:
metadata:
labels:
app: echo
tier: app
version: v2
spec:
containers:
- name: echo
image: ghcr.io/subicura/echo:v2
livenessProbe:
httpGet:
path: /
port: 3000
---
apiVersion: v1
kind: Service
metadata:
name: echo-v2
spec:
ports:
- port: 3000
protocol: TCP
selector:
app: echo
tier: app
version: v2
v1.18 이하 버전
쿠버네티스 v1.19부터 Ingress Spec 중 rules.http.paths.backend
가 변경되었습니다. v1.18 이하라면 pathType
을 제거하고 backend
를 다음과 같이 변경해주세요.
backend:
serviceName: echo-v1
servicePort: 3000
Deployment, Service, Ingress를 생성합니다.
kubectl apply -f echo-v1.yml,echo-v2.yml
# Ingress 상태 확인
kubectl get ingress
kubectl get ing
실행 결과
NAME CLASS HOSTS ADDRESS PORTS AGE
echo-v1 <none> v1.echo.192.168.64.5.sslip.io 192.168.64.5 80 48s
echo-v2 <none> v2.echo.192.168.64.5.sslip.io 192.168.64.5 80 48s
v1.echo.192.168.64.5.sslip.io
과 v2.echo.192.168.64.5.sslip.io
로 접속 테스트합니다.
Docker
Docker driver를 사용중이라면 v1.echo.127.0.0.1.sslip.io:PORT
로 테스트합니다. PORT
는 ingress-nginx-controller
서비스의 첫번째 항목입니다.
# Ingress 생성 흐름
Ingress가 어떻게 동작하는지 알아봅니다.
Ingress Controller
는Ingress
변화를 체크Ingress Controller
는 변경된 내용을Nginx
에 설정하고 프로세스 재시작
동작방식을 보면 YAML로 만든 Ingress 설정을 단순히 nginx 설정으로 바꾸는 걸 알 수 있습니다. 이러한 과정을 수동으로 하지 않고 Ingress Controller가 하는 것 뿐입니다.
Ingress는 도메인, 경로만 연동하는 것이 아니라 요청 timeout, 요청 max size 등 다양한 프록시 서버 설정을 할 수 있습니다. 상세 설정은 추후 고급편에서 다시 다루겠습니다.
# 마무리
Ingress를 사용하면 YAML 설정만으로 도메인, 경로 설정을 손쉽게 할 수 있습니다. 기존에 도메인을 연결하려면 담당자에게 요청하고 설정 파일을 변경한 다음 프로세스 재시작까지 수동으로 작업했는데, 더 이상 그런 과정을 거치지 않아도 됩니다.
# 참고
Ingress v1 networking.k8s.io (opens new window)
# 문제
문제1. 다음 조건을 만족하는 Ingress를 만드세요.
키 | 값 |
---|---|
Deployment 이름 | nginx |
Deployment Label | app: nginx |
Deployment 복제수 | 3 |
Container 이름 | nginx |
Container 이미지 | nginx:latest |
Ingress 도메인 | nginx.xxx.sslip.io |
정답
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
spec:
rules:
- host: nginx.192.168.64.5.sslip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: echo
image: nginx:latest
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
app: nginx