CKA를 준비해보자 34일차 - Ingress

0

CKA

목록 보기
34/43

Ingress

많은 사람들이 헷갈려하는 것 중 하나가 service와 ingress이다.

Ingress는 kubernetes object로서 layer 7에 해당하는 network 기능을 제공해준다. 가령 TLS를 통한 https제공, host name기반의 라우팅, path기반의 라우팅, oauth2 등의 기능을 제공해준다.

wear-pod1---|                    ---ingress---
wear-pod2---|--wear service   -->| http,https|
wear-pod3---|                    | oauth, tls|
                                 | routing   |
video-pod1---|                   |           |
video-pod2---|--video service -->|           |
video-pod3---|                   -------------

wear 기능을 제공하는 pod들이 있다고 하자. 이는 my-app:80/wear로 요청을 받고 싶다. 또한, video역시도 my-app:80/wear로 요청을 받고 싶다.

그러나, 기존의 NodePort로는 port를 30000이상 밖에 사용할 수 밖에 없고, 각 service마다 서로 다른 NodePort를 만들어주는 수 밖에 없다. 즉, wear32080, video32081로 말이다.

이렇게 하나의 platform이 기능마다 port가 달라지면 사용자도 힘들고, 관리하는 입장에서 oauth, https 적용 등을 매번 각 port마다 따로 해주는 방법 밖에 없다.

그래서, ingress가 등장한 것이다. ingressingress-controller라는 component를 통해 동작하게 되는데, cluster의 특정 service와 특정 path를 연결해 layer 7의 기능인 https, oauth 등의 기능을 제공해준다.

이때 ingress-controller는 대부분 NodePort로 열거나 AWS, GCP와 같은 퍼블릭 클라우드에서는 로드밸런서로 외부에 오픈이 된다.

wear-pod1---|                    ---ingress---
wear-pod2---|--wear service   -->| http,https|
wear-pod3---|                    | oauth, tls|
                                 | routing   |-->38080
video-pod1---|                   |           |
video-pod2---|--video service -->|           |
video-pod3---|                   -------------

위와 같이 38080으로 ingress-controller를 외부에 노출시키고, waer service/wear로 맵핑해주는 ingress를 만들어준다. 이렇게하면 38080으로 온 요청 중에 my-app:38080/wear가 있다면 wear service로 맵핑된다.

똑같이 video도 마찬가지이다. video/videovideo service를 연결해주는 ingress를 만들어준다. 따라서 my-app:38080/video로 온 요청은 video service가 받아내게 된다.

그래서 ingress라는 것은 사실 두 가지로 분해할 수 있다.

  1. deploy: ingress 기능을 배포하는 주요 컴포넌트로 ingress controller가 있다. nginx-ingress-controller, traefic이 대표적이다.

  2. configure: 어느 service를 어떤 path, host로 맵핑하고 https, oauth, 로드밸런싱과 같은 기능을 설정하는 부분이다. 이는 Ingress라는 kubernetes object로 설정할 수 있다.

기본적으로 Ingress controller는 설치되지 않아있따.

  • nginx-ingress-controller
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress-controller
spec:
  replicas: 1
  selector:
    matchLabels:
      name: nginx-ingress
  template:
    metadata:
      labels:
        name: nginx-ingress
    spec:
      containers:
      - name: nginx-ingress-controller
        image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.21.0
      args:
        - /nginx-ingress-controller
        - --configmap=$(POD_NAMESPACE)/nginx-configuration
      env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
      ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443

ingress-controller 역시도 다른 pod와 마찬가지인 것이다.

다음으로 ingress-controller를 위한 NodePort service를 만들어주도록 하자.

apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress
spec:
  type: NodePort
  selector:
    name: nginx-ingress
  ports:
    - port: 80
      targetPort: 80
      nodePort: 38080

다음으로 ingress-controller를 위한 ServiceAccount를 제공해주어야 한다.

따라서, ingress controller는 'Deployment', 'Service', 'ServiceAccount'가 필요하다.

다음으로는 'Ingress'를 만들어보도록 하자. Ingress resource는 위에서 설명했듯이 L7 layer의 고도화된 기능을 제공해주는데 path을 기반으로한 라우팅, https, oauth2 등의 기능을 제공해준다. 이 기능들을 어떻게 사용할 것인지 각 Ingress resource에 정의하여 제공해줄 수 있는 것이다.

다음은 위에서 만든 wear pod에 관한 wear-service/wear 요청으로부터 온 packet에 연결해주는 code이다. 가령 ingress controller30080으로 열렸다면 host:30080/wear로 요청이 온 것을 wear-service로 전달해주는 것이다.

  • ingress-wear.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-wear
spec:
  rules:
  - http:
      paths:
      - path: /wear
        pathType: Prefix
        backend:
          service:
            name: wear-service
            port:
              number: 80

만약 /watch path를 watch-service와 연결하고 싶다면 다음과 같이 쓸 수 있다.

  • ingress-wear-watch.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-wear
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /wear
        pathType: Prefix
        backend:
          service:
            name: wear-service
            port:
              number: 80
      - path: /watch
        pathType: Prefix
        backend:
          service:
            name: watch-service
            port:
              number: 80

참고로 annotation부분의 rewrite-targethost:30080/wearhost:30080/watch와 같은 요청을 host:30080/wear/host:30080/watch/로 바꿔준다.

왜 이렇게 바꿔주냐면 보통 웹 서버의 경우 /로 시작하는 경우가 많기 때문이다. 즉 watch pod의 경우 다음과 같이 server를 열었을 것이다.

http://<wear-service>:<port>/

그런데, 만약 rewrite없이 실했다면 host:30080/watch대로 요청이 watch-service로 갔었을 텐데, 그러면 다음에 요청이 간다.

http://<wear-service>:<port>

이렇게 되면 실패하게된다. 이와 같이 요청이 온 path를 보고 연결된 service를 위해 rewrite작업을 거쳐주는 것이다.
https://kubernetes.github.io/ingress-nginx/examples/

위의 링크에서 자세한 내용을 볼 수 있다.

참고로 ingress-nginx-controller를 만들 때, ingress에서 설정한 path가 없다면 default로 적용할 service를 설정할 수 있는데, 다음과 같다.

spec:
  containers:
  - args:
    ...
    - --default-backend-service=app-space/default-backend-service

다음은 default-backend-service로 맵핑되어 있다.

마지막으로 주의할 것은 ingress-controller는 namespace와 상관없이 사용이 가능하지만, ingress의 경우는 namespace에 종속을 받기 때문에 namespace가 서로 다른 service에 대한 연결이 불가능하다.

0개의 댓글