개발/Infra

[k8s] Ingress

devriver 2021. 8. 3. 23:48
대세는 쿠버네티스 [초급~중급] 강의를 보고 정리한 글입니다.
[중급 편] 컨트롤러 Ingress

Ingress use case

Service LoadBalancing

www.mall.com  -> Ingress -> Service1 -> Shopping Pod

www.mall.com/customer  -> Ingress -> Service2 -> Customer Center Pod

www.mall.com/order   -> Ingress -> Service3 -> Order Service Pod  

Canary Upgrade

www.app.com   -> Ingress -> Service1(90%) -> pod1(app v1), pod2(app v1)

www.app.com   -> Ingress -> Service2(10%) -> pod3(app v2) 

 

Ingress 설정 예시

Ingress1

Host: www.app1.com (도메인 이름)

Path: /svc1   ==> ServiceName: Service1

Path: /svc2   ==> ServiceName: Service2

Path: /svc3   ==> ServiceName: Service3

이렇게 Ingress Rule을 만들어도 k8s가 구현체를 만들기 전까지는 아무것도 할 수 없다.

별도의 plugin을 설치해야하며 대표적으로 NGINX, Kong 이 있다.

 

설치 과정

  1. Ingress Controller의 하나인 NGINX를 설치한다.
  2. nginx의 Namespace가 생성되고 그 위에 Deployment, ReplicaSet이 만들어진다.
  3. ReplicaSet에 의해 실제 Ingress 구현체인 Pod가 만들어진다.
  4. 이 Pod에 Ingress Rule이 있는지 확인한다.
  5. Rule이 있다면 Rule에 맞게 각 Service에 연결한다.
  6. 외부에서 들어오는 트래픽을 Rule에 맞게 각 서비스에 전달되도록 하기 위해서는 외부 트래픽은 Ingress Pod를 거쳐야 한다. 이를 위해 외부에서 접근할 수 있는 Service 하나를 만들고 Ingress Pod에 연결한다.
  7. 직접 k8s 설치한 경우는 NodePort, 클라우드를 이용한 경우는 LoadBalancer 를 만들어서 외부 Service에 연결한다.

이제 www.app1.com/svc1  으로 들어오는 트래픽은 외부 Service -> Ingress Pod -> Ingress1 -> Service1 -> Pod1 로 전달된다.

 

이 상태에서 새로운 Ingress 룰을 만든다면?

Ingress2

Host: www.app2.com (도메인 이름)

 ==> ServiceName: Service4

Ingress 구현체가 이미 있기 때문에 Ingress Pod에 Ingress2 룰이 추가되고 www.app2.com  으로 들어오는 트래픽이 Service4로 연결된다.

Ingress의 세가지 기능

Service Loadbalancing

Ingress

Path: /   ==> ServiceName: svc-shopping

Path: /customer   ==> ServiceName: svc-customer

Path: /order   ==> ServiceName: svc-order
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: service-loadbalancing
spec:
  rules:
  - http:
      paths:
        - path: /
          backend:
            serviceName: svc-shopping
            servicePort: 8080
        - path: /customer
          backend:
            serviceName: svc-customer
            servicePort: 8080
        - path: /order
          backend:
            serviceName: svc-order
            servicePort: 8080

Canary Upgrade

Ingress

Host: www.app.com

ServiceName: svc-v1
Ingress(canary)

Host: www.app.com

ServiceName: svc-v2 (app v2 pod로 연결되는 서비스)

 

Ingress(canary)에 어노테이션을 달면 Ingress Controller의 다양한 기능을 사용할 수 있다.

Ingress - @weight: 10% : 트래픽의 10% 가도록

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: canary-v2
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  rules:
  - host: www.app.com
    http:
      paths:
      - backend:
          serviceName: svc-v2
          servicePort: 8080

Ingress - @header : 특정 나라별로 테스트하고 싶을 때. user의 언어가 kr일 때 100% svc-v2로 연결된다.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: canary-kr
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "Accept-Language"
    nginx.ingress.kubernetes.io/canary-by-header-value: "kr"
spec:
  rules:
  - host: www.app.com
    http:
      paths:
      - backend:
          serviceName: svc-v2
          servicePort: 8080

Https

pod 자체에서 인증서 기능 제공하기 힘들 때 사용하면 좋다.

Ingress

rules
host: www.https.com
serviceName: svc-https

tls
secretName: secret-https (secret 객체의 이름을 지정한다)

Secret 안에는 data 값으로 인증서 정보를 가지고 있다. 이렇게 구성하면 사용자는 https 로만 접근 가능하다.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: https
spec:
  tls:
  - hosts:
    - www.https.com
    secretName: secret-https
  rules:
    - host: www.https.com
      http:
        paths:
        - backend:
            serviceName: svc-https
            servicePort: 8080