Ingress 튜토리얼

Ingress는 클러스터 외부의 요청을 Ingress 리소스에 정의된 규칙에 따라 클러스터 내부의 서비스로 연결해줍니다. 더 자세한 설명은 Kubernetes의 Ingress 문서를 참고하시기 바랍니다. 이 가이드에서는 URI에 따른 라우팅과 호스트에 따른 라우팅 두 가지 방법을 설정해보겠습니다.

준비 사항

  • 운영 중인 클러스터와 kubectl 설치 및 환경변수 설정이 필요합니다.
    • 클러스터 생성 시 설치 모듈에서 Ingress Nginx를 선택하여 생성하신 경우, Ingress ControllerService가 자동으로 생성되므로 아래의 EXTERNAL-IP 확인부터 진행하시기 바랍니다.
  • 클러스터 생성은 "클러스터 생성하기"를 참고하시기 바랍니다.
  • kubectl 설치 및 환경변수 설정은 "kubectl 설치하기"를 참고하시기 바랍니다.

Ingress Controller 배포

아래의 명령을 수행하면 ingress-nginx라는 Namespace가 생성되며 Ingress 구현체인 ingress-nginx에 필요한 리소스들이 생성됩니다.

kubectl --kubeconfig $KUBE_CONFIG apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
  • 실행결과
    namespace/ingress-nginx created
    configmap/nginx-configuration created
    configmap/tcp-services created
    configmap/udp-services created
    serviceaccount/nginx-ingress-serviceaccount created
    clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
    role.rbac.authorization.k8s.io/nginx-ingress-role created
    rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
    clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
    deployment.apps/nginx-ingress-controller created
    

Ingress Service 생성

외부에서 접근할 수 있도록 LoadBalancer 타입의 Ingress Service를 생성합니다.

kubectl --kubeconfig $KUBE_CONFIG apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/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를 확인할 수 있고 HOSTSa.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 문서를 참고해주시기 바랍니다.

""에 대한 건이 검색되었습니다.

    ""에 대한 검색 결과가 없습니다.

    처리중...