ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 쿠버네티스 인그레스(kubernetes ingress)
    Kubernetes 2018. 7. 18. 09:00
    반응형
    인그레스(ingress)는 클러스터 외부에서 내부로 접근하는 요청들을 어떻게 처리할지 정의해둔 규칙들의 모음입니다. 외부에서 접근가능한 URL을 사용할 수 있게 하고, 트래픽 로드밸런싱도 해주고, SSL 인증서 처리도 해주고, 도메인 기반으로 가상 호스팅을 제공하기도 합니다. 인그레스 자체는 이런 규칙들을 정의해둔 자원이고 이런 규칙들을 실제로 동작하게 해주는게 인그레스 컨트롤러(ingress controller)입니다. 
    클라우드 서비스를 사용하게 되면 별다른 설정없이 각 클라우드 서비스에서 자사의 로드밸런서 서비스들과 연동해서 인그레스를 사용할 수 있게 해줍니다. 클라우드 서비스를 사용하지 않고 직접 쿠버네티스 클러스터를 구축해서 사용하는 경우라면 인그레스 컨트롤러를 직접 인그레스와 연동해 주어야 합니다. 이때 가장 많이 사용되는건 쿠버네티스에서 제공하는  ingress-nginx(https://github.com/kubernetes/ingress-nginx) 입니다. 
    nginx 인그레스 컨트롤러는 인그레스에 설정된 내용을 nginx 환경설정으로 변경해서 nginx에 적용합니다. 이외에도 다양한 인그레스 컨트롤러가 있습니다. 인그레스용 yaml 템플릿은 다음과 같은 형식으로 작성할 수 있습니다.
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: test
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /
    spec:
      rules:
      - host: foo.bar.com
        http:
          paths:
          - path: /foos1
            backend:
              serviceName: s1
              servicePort: 80
          - path: /bars2
            backend:
              serviceName: s2
              servicePort: 80
      - host: bar.foo.com
        http:
          paths:
          - backend:
              serviceName: s2
              servicePort: 80
    이 인그레스를 생성하면 아래와 같은 결과를 볼 수 있습니다. foo.bar.com으로 요청이 들어오더라도 뒷부분의 경로에 따라 /foos1이면 서비스 s1으로 연결되고 /bars2이면 서비스 s2쪽으로 연결되도록 설정된걸 확인할 수 있습니다. 그리고 또다른 호스트명인 bar.foot.com도 서비스 s2로 연결되어 있습니다. 이처럼 인그레스를 이용하면 외부에서 들어오는 요청을 다양하게 처리할 수 있습니다.



    인그레스 컨트롤러 : nginx
    인그레스는 결국 설정일 뿐이고 이 설정내용대로 동작하는 실제 행위자가 인그레스 컨트롤러 입니다. 인그레스 컨트롤러는 여러가지가 있지만 쿠버네티스가 공식적으로 제공하고 있는건 gce용인 ingress-gce와 nginx용인 ingress-nginx 2가지가 있습니다. ingress-gce는 gce를 이용하면 자동으로 사용할 수 있고 여기서는 직접 설치해서 사용할 수 있는 ingress-nginx를 알아보도록 하겠습니다. ingress-nginx는 github https://github.com/kubernetes/ingress-nginx 에서 확인할 수 있습니다. 
    다음 명령으로 ingress-nginx 를 실행할 수 있습니다.
     kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml

    이제 이 인그레스 컨트롤러에 접근해보기위한 서비스를 만들어 보겠습니다.
    kubectl expose deploy nginx-ingress-controller --type=NodePort -n ingress-nginx


    http://localhost:30821/ 로 접근해 보면 아래처럼 화면이 보이는걸 확인할 수 있습니다.

    설정이 없을때는 기본 벡엔드로 설정된 default backend가 보입니다. 이제 앞에서 ingress로 설정한 foo.bar.com에 접근해 보겠습니다. 기존에 만들어 뒀던 nginx-deployment를 인그레스에 연결하기 위해서 인그레스에 지정했던 s1이라는 이름으로 nginx-deployment의 서비스를 아래처럼 만듭니다.
    kubectl expose deploy nginx-deployment --name s1

    도메인 기반으로 접근해야 하기 때문에 현재 장비의 /etc/hosts파일을 변경해 주어야 합니다.
    sudo vi /etc/hosts를 통해서 아래 내용을 hosts파일에 추가해 줍니다.
    127.0.0.1 foo.bar.com

    이제 브라우저에서 http://foo.bar.com:30821/foos1 에 접근해 봅니다. 다음 그림처럼 nginx화면이 나오는걸 확인할 수 있습니다.



    이제 인그레스 컨트롤러의 nginx에 어떻게 실제 설정이 들어 있는지 확인해 보겠습니다. 다음처럼 인그레스 컨트롤러의 포드 이름을 확인해서 직접 컨테이너에 접속합니다.
    kubectl get pods -n ingress-nginx
    kubectl -n ingress-nginx exec -it nginx-ingress-controller-c6d66b4fb-7bjjp /bin/bash
    컨테이너 안에서 다음 명령으로 nginx 설정을 확인해 봅니다.
    cat /etc/nginx/nginx.conf
    다음처럼 10.1.0.118:80쪽으로 연결되어 있는 설정을 보실 수 있습니다.
        upstream default-s1-80 {
            least_conn;

            keepalive 32;

            server 10.1.0.118:80 max_fails=0 fail_timeout=0;

        }
    여기서 눈여겨 봐야할 점은 10.1.0.118이라는 IP입니다. 인그레스 설정에는 s1 서비스를 foo.bar.com이랑 연결했습니다. 그런데 s1 서비스의 IP를 확인해 보면 10.111.129.110으로 나옵니다. 그럼 10.1.0.118은 어디서 온 IP일까요? nginx에 설정된 ip는 포드의 ip입니다. 인그레스 컨트롤러를 통해서 트래픽이 전달될때 중간에 서비스를 거치지 않고 직접 포드로 연결되는 구조입니다. 이 예제에서는 인그레스 컨트롤러자체도 쿠버네티스 클러스터 위에서 돌아가기 때문에 인그레스 컨트롤러에 접근하기위해서 NodePort타입의 서비스를 만들어 줬습니다. 하지만 인그레스 컨트롤러의 네트워크 옵션을 호스트모드로 주게 되면 별도의 노드포트 없이도 인그레스 컨트롤러에 접근가능하게 되고 다시 거기서 포드로 직접 접근가능하게 되기 때문에 중간에 서비스들을 생략해서 좀 더 좋은 성능을 가질 수 있게 됩니다. 구조는 다음 그림과 같습니다.


    반응형

    댓글

Designed by Tistory.