콤퓨우터/필기: KodeKloud CKA 강의

230. Ingress

파란화면 2024. 5. 17. 00:50
반응형

시나리오 1: 온프레

다음은 MySQL Pod와 (3개의 Replica된 Pod으로 구성된) Deployment로 구성된 간단한 웹사이트의 구성이다.

  • MySQL과 웹서버 간의 통신을 위해 mysql-service ClusterIP Service를 생성
  • 웹서버의 외부 노출을 위해 wear-service NodePort Service를 생성

이 구성은 작동하지만, 문제가 있다

  • 포트 38080을 접속하는 사용자가 꼬박꼬박 입력해주어야함
    • 80같이 낮은 포트는 NodePort Service에 할당할 수가 없다!

따라서 38080 앞에 80을 listen하는 리버스프록시를 추가해서 사용자 접속을 받은 뒤 38080으로 넘겨주는 구성으로 바꿀 수 있을것이다.

 

시나리오 2: GCP

위와 같은 온프레 구성이 아니라, GCP같은 퍼블릭클라우드 상에서 위의 애플리케이션을 구성한다고 해 보자

  • 그렇다면 wear-service 서비스 종류를 NodePort가 아니라 LoadBalancer로 지정할 수도 있을 것이다
    • LoadBalancer구성에서는, 쿠버는 일단 NodePort에서처럼 높은 포트(38080같은)를 할당하지만, 동시에 GCP에 로드밸런서를 생성하도록 GCP API를 부른다
    • GCP 로드밸런서 역시 리버스 프록시로 기능하여 클라이언트로부터 80을 listen하고 38080에 붙는다
      • DNS를 해당 로드밸런서의 IP로 잡아주면 도메인:80으로 해당 사이트에 접속할 수 있을것이다

 

시나리오 3: 새로운 애플리케이션의 추가

위의 시나리오를 확장하여, my-online-store.com/watch에 접속했을 때 비디오 스트리밍 서비스를, my-online-store.com/wear에 접속했을 때 기존의 서비스를 제공하는 시나리오를 구성해야 한다고 해 보자

  • 기존 서비스와 새로운 비디오 스트리밍 서비스는 완전히 다른 애플리케이션이지만, 같은 클러스터의 리소스를 공유하기 위하여, 비디오 스트리밍 역시 같은 클러스터에 별도의 Deployment로 구현
    • 또, 여기에 대한 새로운 LoadBalancer 서비스를 생성
      • GCP는 이에 대한 새로운 로드밸런서를 배치함 (돈은 더 든다)
    • 게다가 같은 서브도메인을 공유하면서 URL 파라미터로 다른 서비스를 매칭시켜야 하기 때문에 로드밸런서가 또 필요함
      • 돈이 더 더 든다
    • 여기에 TLS 설정, 방화벽 설정, ... 같은 설정을 추가해야 한다고 하면 그만큼 설정을 더 잡아줘야함
      • 더 나은 선택지는 없을까요???

 

Ingress로 해결

Ingress를 이용하면, 클러스터 내에서 다양한 서비스로 들어가는 route를 URL 기반으로 설정할 수 있다

  • Ingress 또한 외부로 노출해 줄 필요는 있다 (NodePort나 LoadBalancer 사용)

어떻게 작동하는가?

만약 Ingress가 없다고 가정하면, URL에 따른 route나 SSL 설정 등은 nginx나 HAProxy 같은 reverse proxy를 Pod로 디플로이하여 구현할 수 있었을것이다.

  • Ingress도 사실 똑같이 동작한다!
    • 먼저 nginx, haproxy 등을 디플로이하고(이것을 Ingress Controller라고 한다)
    • 그 다음에 rule들을 설정한다 (이것을 ingress resources라고 한다)

주의할 점은, Ingress Controller는 쿠버에 포함되어 있지 않다는 것이다

  • 사실, 쿠버 1.19 이후로 Ingress의 추가개발은 중지되고 Gateway API로 대체될 예정이지만, CKA 1.29 시험에서도 Gateway API가 아니라 Ingress를 다루고 있으므로 Ingress를 잘 알아두자.

 

Ingress Controller의 종류

  • GCP Application Load Balancer
  • nginx
  • haproxy, traefik, ...

주의할 점은 Ingress Controller == nginx가 아니라는 점이다

  • nginx는 Ingress Controller를 구성하는 가장 큰 구성요소이지만, Ingress Controller 그 자체는 아님
    • 쿠버 클러스터 모니터링을 통해 ingress resources 변경을 감지하고 nginx 설정을 변경해주는 시스템이 탑재되어 있음

 

Ingress Controller의 생성

Ingress Controller의 nginx 파트는 일반적인 Deployment와 거의 같음
차이점:

  • 일반 NGINX 이미지가 아니라 쿠버네티스 전용 빌드를 사용
  • nginx image와 설정값을 분리하기 위해 설정값을 담을 ConfigMap
  • Pod의 이름과 네임스페이스를 담을 Env Var
  • Ingress Controller에서 사용할 포트
spec:
  replicas: 1
  selector:
    matchLabels:
      name: nginx-ingress
  template:
     metadata;
       labels:
         name: nginx-ingress
     spec:
       containers:
         args:
         - /nginx-ingress-controller
         - --configmap=$(POD_NAMESPACE)/nginx-configuration
         env:
         - name: POD_NAME
           valueFrom:
             fieldRef:
               fieldPath: metadata.name 
         - name: POD_NAMESPACE
           # ...
        ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443

또, 외부에 Ingress Controller를 노출하기 위해 NodePort 서비스를 label selector를 곁들여 생성

spec:
  type: NodePort
  #...
  selector:
    name: nginx-ingress

마지막으로, Ingress Controller에 내장된 쿠버네티스 클러스터 모니터링 기능을 사용하기 위하여 적절한 권한이 있는 ServiceAccount를 설정하여야 함

 

Ingress Resource의 생성

예를 들어, 다음과 같은 시나리오를 설정할 수 있다

  • 모든 inbound 트래픽을 특정 애플리케이션에 전달
  • URL별로 다른 애플리케이션에 트래픽을 라우팅
  • 서브도메인별로 다른 애플리케이션에 트래픽을 라우팅

조합도 가능하다

  • 서브도메인별로 다른 애플리케이션에 트래픽을 라우팅하면서 URL별 규칙을 적용하는 것도 가능

간단한 Ingress Resource Object definition file의 예시:

  • 주의: 강의에서는 구버전(extensions/v1beta1) Ingress 정의를 보여주고 있다. 새로운 API(networking.k8s.io/v1)
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: ingress-video
    spec:
    backend:
      service:
        name: video-service
        port: 
          number: 80

시나리오 3의 해결

my-online-store.com/watch에 접속했을 때 비디오 스트리밍 서비스를, my-online-store.com/wear에 접속했을 때 기존의 서비스를 제공하는 시나리오였다.

  • Rule: domain match www.my-online-store.com
  • Path: /wear, /watch
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-wear-watch
  annotati
spec:
  rules:
  - http:
    paths:
    - path: /wear
      backend:
        service:
          name: video-service
          port: 
            number: 80

    - path: /watch
      backend:
        service:
          name: watch-service
          port: 
            number: 80
  • spec.rules.host[]를 명시하지 않았으므로, 이 규칙은 모든 호스트(도메인)에 대해 매칭된다.

서브도메인을 이용한 라우팅

wear.my-online-store.comwatch.my-online-store.com에 대해, 각각 다른 애플리케이션에서 서비스를 제공하는 시나리오이다.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-wear-watch-subdomains
spec:
  rules:
  - host: wear.my-online-store.com
    http:
      paths:
      - backend:
          serviceName: wear-service
          servicePort: 80

  - host: watch.my-online-store.com
    http:
      paths:
      - backend:
          serviceName: watch-service
          servicePort: 80
# kubectl describe ingress ingress-wear-watch -n app-space
Name:             ingress-wear-watch
Labels:           <none>
Namespace:        app-space
Address:          10.99.182.171
Ingress Class:    <none>
Default backend:  <default>
Rules:
  Host        Path  Backends
  ----        ----  --------
  *           
              /wear    wear-service:8080 (10.244.0.4:8080)
              /watch   video-service:8080 (10.244.0.5:8080)
Annotations:  nginx.ingress.kubernetes.io/rewrite-target: /
              nginx.ingress.kubernetes.io/ssl-redirect: false
Events:
  Type    Reason  Age                From                      Message
  ----    ------  ----               ----                      -------
  Normal  Sync    31s (x2 over 31s)  nginx-ingress-controller  Scheduled for sync
  • 호스트가 * (전체 도메인 매칭)
  • Default backend: <default>
    • path와 매칭되지 않은 요청은 app-space/default-backend-service로 보내진다
      • 이유: spec.template.spec.containers[].args[]--default-backend-service=app-space/default-backend-service로 되어 있기 때문
kubectl get deployment -A -o wide
NAMESPACE       NAME                       READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS      IMAGES                                                                                                                    SELECTOR
app-space       default-backend            1/1     1            1           116s    simple-webapp   kodekloud/ecommerce:404                                                                                                   app=default-backend
app-space       webapp-video               1/1     1            1           116s    simple-webapp   kodekloud/ecommerce:video                                                                                                 app=webapp-video
app-space       webapp-wear                1/1     1            1           116s    simple-webapp   kodekloud/ecommerce:apparels                                                                                              app=webapp-wear
ingress-nginx   ingress-nginx-controller   1/1     1            1           114s    controller      registry.k8s.io/ingress-nginx/controller:v1.1.2@sha256:28b11ce69e57843de44e3db6413e98d09de0f6688e33d4bd384002a44f78405c   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
kube-system     coredns                    2/2     2            2           6m40s   coredns         registry.k8s.io/coredns/coredns:v1.10.1                                                                                   k8s-app=kube-dns
반응형

'콤퓨우터 > 필기: KodeKloud CKA 강의' 카테고리의 다른 글

252-261. Troubleshooting  (0) 2024.05.17
241. etcd in HA  (0) 2024.05.17
226-227. DNS and CoreDNS in Kubernetes  (1) 2024.05.17
223. Service Networking  (0) 2024.05.17
215. CNI Weave  (0) 2024.05.17