Ingress 튜토리얼
    • PDF

    Ingress 튜토리얼

    • PDF

    Article Summary

    Classic 환경에서 이용 가능합니다.

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

    준비 사항

    운영 중인 클러스터와 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의 문서에서 확인할 수 있으며, 각 서비스에 맞는 설정으로 변경하시는 것을 권장해 드립니다.


    이 문서가 도움이 되었습니까?

    Changing your password will log you out immediately. Use the new password to log back in.
    First name must have atleast 2 characters. Numbers and special characters are not allowed.
    Last name must have atleast 1 characters. Numbers and special characters are not allowed.
    Enter a valid email
    Enter a valid password
    Your profile has been successfully updated.