- 인쇄
- PDF
Ingress 튜토리얼
- 인쇄
- PDF
Classic 환경에서 이용 가능합니다.
Ingress는 클러스터 외부의 요청을 Ingress 리소스에 정의된 규칙에 따라 클러스터 내부의 서비스로 연결해줍니다.
더 자세한 설명은 Kubernetes의 Ingress 문서를 참조하시기 바랍니다.
이 가이드에서는 URI에 따른 라우팅과 호스트에 따른 라우팅 두 가지 방법을 설정해 보겠습니다.
준비 사항
운영 중인 클러스터와 kubectl 설치 및 환경변수 설정이 필요합니다.
- 클러스터 생성은 클러스터 생성하기를 참조하시기 바랍니다.
- kubectl 설치 및 환경변수 설정은 kubectl 설치하기를 참조하시기 바랍니다.
클러스터 생성 시 설치 모듈에서 Ingress Nginx를 선택하여 생성하신 경우, Ingress Controller와 Service가 자동으로 생성되므로 아래의 EXTERNAL-IP 확인부터 진행하시기 바랍니다.
Ingress Controller 배포
ingress-nginx 공식문서에서 azure의 설치 예시를 참고하여 ingress-nginx를 설치합니다.
https://kubernetes.github.io/ingress-nginx/deploy/#azure
Ingress Service 생성
외부에서 접근할 수 있도록 LoadBalancer 타입의 Ingress Service를 생성합니다.
kubectl --kubeconfig $KUBE_CONFIG apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/2de5a893aa15f14102d714e918b0045b960ad1a5/deploy/static/provider/cloud-generic.yaml
- 실행 결과
service/ingress-nginx created
로드밸런서 생성 여부 실시간 확인
kubectl --kubeconfig $KUBE_CONFIG get service -n ingress-nginx --watch
- 실행 결과
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx LoadBalancer 172.17.116.11 <pending> 80:31583/TCP,443:32586/TCP 4s
ingress-nginx LoadBalancer 172.17.116.11 slb-1976810.n... 80:31583/TCP,443:32586/TCP 27s
EXTERNAL-IP 확인
Service가 pending 상태에서 생성이 완료되면 EXTERNAL-IP를 확인합니다.
kubectl --kubeconfig $KUBE_CONFIG get service -n ingress-nginx
- 실행 결과
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx LoadBalancer 172.17.116.11 slb-1976810.ncloudslb.com 80:31583/TCP,443:32586/TCP 59s
Application 및 서비스 배포
각자 다른 정보를 가진 두 개의 예제용 Deployment 및 Service를 생성합니다. 예제용 Deployment는 자신의 호스트 정보를 보여주는 demo용 nginx container이며, 각 Service는 ClusterIP 타입으로 생성되어 외부에서 직접 접근이 불가능한 상태입니다.
kubectl --kubeconfig $KUBE_CONFIG apply -f https://gist.githubusercontent.com/NaverCloudPlatformDeveloper/c47620d8d25b2a0e08648f225043adf6/raw/675addde0a56ba727824f30f92a73b40550fb73c/nks-tutorial-hello-service.yaml
- 실행 결과
deployment.apps/a created
service/a-svc created
deployment.apps/b created
service/b-svc created
URI 기반 라우팅
앞에 생성한 Ingress Service의 External IP 뒤에 붙는 Path별로 라우팅을 해서 /a로 요청할 때와 /b로 요청할 때 각각 다른 서비스로 연결되도록 설정해보겠습니다.
Ingress 생성
예제의 Ingress 리소스는 아래와 같이 각 path에 따라 backend를 다르게 설정하여 /a로 접근할 경우 a-svc로, /b로 접근할 경우는 b-svc로 접근하도록 설정했습니다.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ab-ingress
annotations:
kubernetes.io/ingress.class: nginx
ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- http:
paths:
- path: /a
backend:
serviceName: a-svc
servicePort: 80
- path: /b
backend:
serviceName: b-svc
servicePort: 80
아래의 명령으로 Ingress를 생성합니다.
kubectl --kubeconfig $KUBE_CONFIG apply -f https://gist.githubusercontent.com/NaverCloudPlatformDeveloper/eca9d12336e008f1c7102892750aeae5/raw/3f3d0916d89161a1d81ed19464b9991154a8b9f8/nks-tutorial-ab-ingress.yaml
- 실행 결과
ingress.extensions/ab-ingress created
예제에서는 TLS 설정을 하지 않았기 때문에 강제 redirection을 막기 위해서 ingress annotation에 nginx.ingress.kubernetes.io/ssl-redirect: "false"를 추가했지만, TLS 설정 시에는 해당 annotation을 지워주시기 바랍니다.
Ingress 생성 확인
kubectl get ingress 명령으로 생성된 ingress를 확인할 수 있습니다.
kubectl --kubeconfig $KUBE_CONFIG get ingress
- 실행 결과
NAME HOSTS ADDRESS PORTS AGE
ab-ingress * slb-1976810.ncloudslb.com 80 19s
서비스 접속 확인
브라우저 또는 curl을 통해 접속 결과를 확인하면 각자 다른 Service의 Pod로 접근하는 것을 확인할 수 있습니다.
예시
- http://slb-1976810.ncloudslb.com/a
$ curl http://slb-1976810.ncloudslb.com/a
Server address: 172.24.21.10:80
Server name: a-57598bbddd-9hcc6
Date: 09/Jul/2019:09:03:36 +0000
URI: /a
Request ID: add732582fb99d0cfffe3edc83169517
- http://slb-1976810.ncloudslb.com/b
$ curl http://slb-1976810.ncloudslb.com/b
Server address: 172.24.21.11:80
Server name: b-657f4794f4-k48hb
Date: 09/Jul/2019:09:03:37 +0000
URI: /b
Request ID: 6cfd25c99f677c75ad815eaf57fc24c5
호스트 기반 라우팅
이번에는 동일한 EXTERNAL-IP에 대해 각각 다른 도메인으로 요청 시 다른 서비스로 연결되도록 설정해보겠습니다.
기존 ingress 삭제
먼저 앞에 생성했던 ab-ingress를 삭제합니다.
kubectl --kubeconfig $KUBE_CONFIG delete ingress ab-ingress
- 실행 결과
ingress.extensions "ab-ingress" deleted
Ingress 생성
아래 예제는 a.svc.com으로 요청할 경우는 a-svc로, b.svc.com으로 요청할 경우는 b-svc로 연결하도록 각각의 host에 따라 backend를 다르게 했습니다.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ab-host-ingress
annotations:
kubernetes.io/ingress.class: nginx
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: a.svc.com
http:
paths:
- path: /
backend:
serviceName: a-svc
servicePort: 80
- host: b.svc.com
http:
paths:
- path: /
backend:
serviceName: b-svc
servicePort: 80
아래의 명령으로 Ingress를 생성합니다.
kubectl --kubeconfig $KUBE_CONFIG apply -f https://gist.githubusercontent.com/NaverCloudPlatformDeveloper/39913ee1025c45aaa0d50753db8a7555/raw/91082b01c0f26313b0a11e61df8984ac6c6b5c46/nks-tutorial-ab-host-ingress.yaml
- 실행 결과
ingress.extensions/ab-host-ingress created
Ingress 생성 확인
kubectl get ingress 명령으로 생성된 ingress를 확인할 수 있고 HOSTS에 a.svc.com, b.svc.com이 있는 것을 볼 수 있습니다.
kubectl --kubeconfig $KUBE_CONFIG get ingress
- 실행 결과
NAME HOSTS ADDRESS PORTS AGE
ab-host-ingress a.svc.com,b.svc.com slb-1976810.ncloudslb.com 80 3m57s
서비스 접속 확인
예제의 호스트로 설정한 도메인은 실제로는 없는 도메인이기 때문에 curl 명령에 -H host 옵션을 넣어서 호스트별 접속 시에 다른 서비스가 노출되는지 확인해봅니다.
예시
- a.svc.com
$ curl -H host:a.svc.com http://slb-1976810.ncloudslb.com
Server address: 172.24.21.10:80
Server name: a-57598bbddd-9hcc6
Date: 09/Jul/2019:08:33:03 +0000
URI: /
Request ID: b340711ab142bef67fdb07e7fd077ddb
- b.svc.com
$ curl -H host:b.svc.com http://slb-1976810.ncloudslb.com
Server address: 172.24.21.11:80
Server name: b-657f4794f4-k48hb
Date: 09/Jul/2019:08:33:12 +0000
URI: /
Request ID: eb6a876acbb2db7155ff26992b6635e4
참고 사항
이름에 _(underscore)가 있는 Request Header는 서버에서 확인이 되지 않습니다.
ingress-nginx에서는 request header 이름에 _(underscore)가 들어가면 강제로 삭제합니다. 이를 회피하기 위해서는 ConfigMap에 enable-underscores-in-headers: true를 추가해야 합니다. 자세한 내용은 ingress-nginx의 ConfigMaps 문서를 참조하시기 바랍니다.
서버에서 Request의 Client IP를 확인하면 Cluster 내부의 IP로 보입니다.
ingress-nginx를 통해 Client의 Real IP를 온전하게 취득하기 위해서는 LoadBalancer의 proxy protocol 설정과 ingress-nginx의 use-proxy-protocol: true ConfigMap이 설정되어 있어야 합니다.
LoadBalancer의 proxy protocol 활성화는 "Kubernetes의 서비스를 통한 로드밸런서 연동"을 참조해 주시고
ingress-nginx의 ConfigMap 설정은 ingress-nginx의 ConfigMaps 문서를 참조해 주시기 바랍니다.
Load Balancer에서 ingress-nginx Pod가 없는 Node는 Health Check에 실패하는 것으로 나옵니다.
위 예시로 ingress-nginx Service를 생성한 경우 Service .spec.externalTrafficPolicy: Local로 설정되어 있는 것을 확인 할 수 있습니다.
.spec.externalTrafficPolicy는 서비스에서 외부 트래픽을 어떻게 라우팅 하는지를 설정할 수 있습니다. 사용 가능한 값은 Cluster(default)와 Local입니다.
- Cluster: 외부 트래픽을 전체 Pod에 분산합니다. 다른 Node에 있는 Pod로 전달할 때 두 번째 홉을 유발할 수 있지만, Pod로의 트래픽은 균형있게 분산할 수 있습니다.
- Local: 외부 트래픽을 로컬 Node에 있는 Pod로만 전달합니다. 다른 Node에 대한 두 번째 홉을 피하지만 불균형한 트래픽 분산이 발생할 수 있습니다.
ingress-nginx Service의 .spec.externalTrafficPolicy: Local로 되어있다면 ingress-nginx Pod가 동작 중인 Node만 트래픽이 전달되므로 그 외의 서버는 Health Check에 실패하는 것으로 나옵니다.
동작에 대한 자세한 내용은 Kubernetes의 문서에서 확인할 수 있으며, 각 서비스에 맞는 설정으로 변경하시는 것을 권장해 드립니다.