Kubernetes 리소스 Ingress에 대해 이해하고 실습해보기

Bakumando·2022년 5월 27일
2

Kubernetes

목록 보기
14/17

들어가기에 앞서...

  • 본 글은 쿠버네티스 시리즈 중의 하나로, kubernetes 실습을 위한 기본 환경 세팅이 이루어져 있지 않은 분은 시리즈 1편을 확인해주시길 바란다.
  • 쿠버네티스 실습 시리즈는 아래 학습 자료를 참고하고 있다.

0. 블로깅 목적

  • Ingress가 무엇인지 알고, Ingress 컨트롤러와 Ingress 클래스를 이해한다.
  • Nginx Ingress 컨트롤러를 이해하고 실습한다.

1. Ingress가 무엇인지 알고, Ingress 컨트롤러와 Ingress 클래스를 이해한다.

1) Ingress?

(1) 간단 정의

  • 외부로부터의 요청에 대해 TLS 설정 관리 및 라우팅 관리를 하는 리소스를 Ingress라 한다.

(2) 상세 설명

  • Ingress는 L7에서 라우팅 기능을 수행할 수 있다.
  • Ingress는 SSL / TLS 통신 암호화 처리를 할 수 있다. (각 연결 호스트에 대한 인증서 적용)
  • Service 리소스가 L4(전송 계층) 레벨에서 이게 이루어진다면, Ingress는 L7(어플리케이션 계층) 레벨에서 외부 요청을 처리하게 되는 것이다.
  • 오해하지 말아야할 것은 Ingress를 사용하게 되더라도 Service를 사용하지 않는 게 아니라, 함께 사용하게 된다. (위 그림 참고)
    1. Ingress가 마치 Gateway처럼 앞단에서 요청을 받는다
    2. L7 계층(HTTP 레벨)에서 Host 단위나 Path 단위로 라우팅 처리를 하여 어떤 Service로 보내줄 지를 결정을 한다.
    3. L4 계층(TCP/IP 레벨)에서 Pod로 로드밸런싱을 진행하게 된다.


2) Ingress 컨트롤러

(1) 간단 정의

  • 쿠버네티스 클러스터는 기본적으로 Ingress API 리소스를 다루는 Ingress Controller를 제공하지 않는다. Ingress API 리소스에 대한 스펙만 제공한다.
    • 그래서 이 스펙을 처리할 수 있는 Ingress Controller가 필요하다. 즉, 사용자가 직접 원하는 Ingress 컨트롤러를 설치해야만 한다.
    • 이렇게 설정한 이유는 Ingress 서버 역할을 수행할 수 있는 Gateway 존재가 굉장히 많기 때문이다. 사용자에게 선택권을 주는 것이다.

(2) 대표 Ingress Controller

  • Envoy Ingress Controller
  • Traffic Ingress Controller
  • HAProxy Ingress Controller
  • NGINX Ingress Controller
  • Kong Ingress Controller
  • AWS Load Balancer Controller
  • Google Load Balancer Controller
    => minikube에는 NGINX Ingress Controller가 포함되어 있다.
    => 이 중 클라우드 프로바이더는 AWS, Google 등이다.

(3) Ingress Class (인그레스 클래스)

  • 하나의 클러스터에서 여러 인그레스 컨트롤러를 사용할 수 있도록 하기 위해 만들어진 API 리소스
  • IngressClass = IngressController + Configuration
  • 즉 실제 인그레스(Ingress)는 하나의 인그레스 클래스와 연결을 하게 된다. 그리고 그 인그레스 클래스가 사용하는 인그레스 컨트롤러를 통해서 규칙이 정해진다고 보면 된다.
    • nginx 컨트롤러를 사용하는 인그레스는 사실 nginx 서버를 가리킨다기 보다는, nginx 서버에 올라가는 라우팅 규칙 및 TLS 설정을 정의한다.
    • aws loadbalancer 컨트롤러를 사용하는 인그레스는 이 로드밸런서의 리스너(라우팅 규칙)들과 TLS certificate를 정의하게 된다.

2. Nginx Ingress 컨트롤러를 이해하고 실습한다.

1) Nginx Ingress 컨트롤러


2) AWS Load Balancer 컨트롤러

  • AWS에서 관리하는 오픈소스 컨트롤러로 다음의 기능을 제공한다.
    • AWS ALB(Application LoadBalancer) 기반의 Ingress Controller
    • AWS NLB(Network LoadBalancer) 기반의 LoadBalancer 타입 Service
  • 링크: https://github.com/kubernetes-sigs/aws-load-balancer-controller
  • 이번 챕터에서 실습으로 다루진 않을 것이다.


3) Nginx Ingress 컨트롤러를 활용하여 실습한다.

  • m1에서 ingress 실습이 까다로울 수 있어서 ubuntu로 진행하였다.
  • 참고로 ubuntu는 UTM(가상머신)으로 설치하였고, m1으로 ubuntu ssh 접속을 통해 실습을 진행하였다.
  • ingress 폴더를 만들고 3개의 yml을 준비한다.
  • ingress 폴더안에 grafana, hello, httpd 폴더를 추가로 만들고 각각에 yml을 2개씩 또 만든다.

ingress-path.yml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /hello
        pathType: Prefix
        backend:
          service:
            name: hello
            port:
              name: http
  - http:
      paths:
      - path: /grafana
        pathType: Prefix
        backend:
          service:
            name: grafana
            port:
              name: http

ingress-host.yml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: host
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: hello.bakumando
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: hello
            port:
              name: http
  - host: grafana.bakumando
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: grafana
            port:
              name: http

ingress-default-backend.yml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: default-backend
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  defaultBackend:
    service:
      name: httpd
      port:
        number: 80
  rules:
  - host: hello.bakumando
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: hello
            port:
              name: http
  - host: grafana.bakumando
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: grafana
            port:
              name: http
  • ingress 테스트를 위한 3가지 yml 파일들을 준비했다. 이에 대한 설명은 하나씩 실습을 하면서 진행해보자.

grafana/deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: grafana
  labels:
    app: "grafana"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: "grafana"
  template:
    metadata:
      labels:
        app: "grafana"
    spec:
      containers:
      - name: grafana
        image: grafana/grafana:latest
        ports:
        - name: http
          containerPort: 3000

grafana/service.yml

apiVersion: v1
kind: Service
metadata:
  name: grafana
  labels:
    app: "grafana"
spec:
  type: ClusterIP
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 3000
  selector:
    app: "grafana"
  • grafana 폴더에 deployment와 service yml을 각각 만든다.

hello/deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      name: hello
      labels:
        app: hello
    spec:
      containers:
      - name: nginx
        image: nginxdemos/hello:plain-text
        ports:
        - name: http
          containerPort: 80
          protocol: TCP

hello/service.yml

apiVersion: v1
kind: Service
metadata:
  name: hello
  labels:
    app: hello
spec:
  type: ClusterIP
  ports:
  - name: http
    protocol: TCP
    port: 8080
    targetPort: 80
  selector:
    app: hello
  • hello 폴더에 deployment와 service yml을 각각 만든다.

httpd/deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd
  labels:
    app: "httpd"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: "httpd"
  template:
    metadata:
      labels:
        app: "httpd"
    spec:
      containers:
      - name: httpd
        image: httpd:latest
        ports:
        - name: http
          containerPort: 80

httpd/service.yml

apiVersion: v1
kind: Service
metadata:
  name: httpd
  labels:
    app: "httpd"
spec:
  type: ClusterIP
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
  selector:
    app: "httpd"
  • httpd 폴더에 deployment와 service yml을 각각 만든다.

(1) ingress 기본 세팅 및 조회

  • kubectl apply -f grafana/
  • kubectl apply -f hello/
  • kubectl apply -f httpd/
    • 만들어둔 deployment, service yml을 전부 적용한다.
  • kubectl get all
    • 생성 결과를 조회해본다.

  • minikube addons list
    • ingress가 disabled인걸 확인할 수 있다.
  • minikube addons enable ingress
    • 이어서 바로 ingress를 설치한다.

  • kubectl get ns
    • namespace를 조회한다. 그럼 ingress-nginx라는 ns가 새로 생긴 걸 볼 수 있다.
  • kubectl get all -n ingress-nginx
    • ingress-nginx 네임스페이스에 대한 전체 오브젝트 조회를 해본다.
    • 여러가지 오브젝트들이 생성되어 있음을 알 수 있다.

  • kubectl get ingressclass
    • ingress 클래스도 조회해본다. 클래스로 nginx가 적용된 걸 확인할 수 있다.
  • kubectl get ingressclass nginx -o yaml
    • 이렇게 yaml 파일로도 출력해볼 수 있다.

(2) ingress-path 실습

  • cat ingress-path.yml
    • 명세를 보면 name은 path인 걸 확인할 수 있고, ingressClassName도 nginx인 걸 알 수 있다.
    • http.paths.path가 /hello일 경우, hello service에 http 포트로 보내라 라는 정의가 되어 있다.
    • http.paths.path가 /grafana일 경우, grafana service에 http 포트로 보내라 라는 정의가 되어 있다.

  • kubectl apply -f ingress-path.yml
  • kubectl get ingress
    • ingress-path.yml를 적용한 뒤에 ingress 목록을 조회해보았다.
    • name은 path, class는 nginx을 사용하도록 하는 ingress 오브젝트가 생성되었음을 알 수 있다.

  • kubectl get service -n ingress-nginx
    • ingress-nginx라는 ns(namespace)의 service를 조회한 것이다. ingress-nginx의 컨트롤러도 service형태로 띄워진다는 걸 확인할 수 있다. 서비스 타입은 NodePort이고 모든 Node가 공통의 포트로 오픈되어 외부 트래픽을 받게 된다.
    • 접근 가능한 URL은 {Node IP}:{NodePort} 형식이다.
  • kubectl get node -o wide
    • Node IP를 조회해보자. 192.168.49.2이다.
    • Node Port는 위에서 이미 조회하였다. http는 32655이다.

  • curl http://192.168.49.2:32655
    • nginx로 연결된 걸 알 수 있다.
  • curl http://192.168.49.2:32655/grafana
  • curl http://192.168.49.2:32655/hello
    • grafana, hello 경로 접근도 잘 이루어진다는 걸 알 수 있다.

  • kubectl delete -f ingress-path.yml
    • ingress-path.yml를 지워준다.

(3) ingress-host 실습

  • cat ingress-host.yml
    • ingress-path와 다른 건 동일한데, rules의 host가 추가되었고, path가 변경되었다.
    • 들어오는 요청에 대해서 host가 hello.bakumando면, hello service의 http 포트로 보내라는 정의를 하였다.
    • 반면 host가 grafana.bakumando면, grafana service의 http 포트로 보내라는 정의를 하였다.

  • kubectl apply -f ingress-host.yml
  • kubectl get ingress
    • ingress-host.yml을 적용하고, ingress를 조회하였다.
    • name은 host, class는 nginx를 사용하도록 되어있고 hosts도 2가지가 잘 설정되어 있다.

  • curl http://192.168.49.2:32655
    • 마찬가지로 ingress controller 서비스의 Node Ip와 Port를 토대로 조회하면 된다.
    • 역시나 nginx가 잘 연결된다.
  • curl http://192.168.49.2:32655 -H "Host: hello.bakumando"
  • curl http://192.168.49.2:32655 -H "Host: grafana.bakumando"
    • 조회 -H "Host: {host 값}" 형식을 추가해주면 된다.
    • 여기서 -H는 http header를 의미한다. 즉 header를 변경해주면 되는 것이다. 그 뒤에는 형식에 맞춰 설정한 값을 잘 넣어주면 된다.
    • hello.bakumando, grafana.bakumando host 둘다 잘 접근되었다.
    • 물론 실제 현업에서는 header값을 변조하지 않는다. 실제 쿠버네티스 클러스터 상의 도메인 설정을 해준다.

  • kubectl delete -f ingress-host.yml
    • ingress-host.yml를 제거해준다.

(4) ingress-default-backend 실습

  • cat ingress-default-backend.yml
    • ingress-host와 거의 동일한데, defaultBackend라는 부분이 추가되었다. defaultBackend 속성은 아래 rules 중에 아무것도 속하지 못할 경우에 해당 백엔드로 보내라는 것이다.
    • 즉, 앞선 두번의 실습에선 경로나 호스트를 제대로 명시해주지 않으면 그냥 nginx not found 404 결과가 나왔었는데, defaultBackend를 정의하게 되면 그 아래 service 설정대로 응답을 받게된다.
    • defaultBackend를 httpd라는 이름으로 정의해두었다.

  • kubectl apply -f ingress-default-backend.yml
  • kubectl get ingress
    • ingress-default-backend.yml를 적용하고 조회하였다.
    • name은 default-backend, class는 nginx를 사용하도록 되어있고, hosts도 이전과 같다.

  • curl http://192.168.49.2:32655 -H "Host: hello.bakumando"
  • curl http://192.168.49.2:32655 -H "Host: grafana.bakumando"
    • 호스트값을 토대로 돌아오는 접근 결과는 이전과 같다.

  • curl http://192.168.49.2:32655 -H "Host: bakumando"
    • 설정되어있지 않은 호스트값을 넣었더니, nginx 404가 아닌 다른 결과가 나오는 걸 볼 수 있다.
    • 이게 바로 defaultBackend 속성을 정의했기 때문이며, 거기에 httpd로 응답되도록 설정 해뒀기 때문에, httpd 컨테이너의 결과인 것이다.
profile
그렇게 바쿠만도는 개발에 퐁당 빠지고 말았답니다.

0개의 댓글