후니의 IT인프라 사전
[KANS-9주차] Ingress와 Gateway API 본문
Ingress 소개
Ingress는 클러스터 내부의 서비스(Cluster IP, NodePort 등)를 외부로 노출시켜 Web Proxy 역할을 하는 쿠버네티스 오브젝트이다.
기존에 NodePort는 노드 포트를 노출해야하는 단점이 있으므로 대부분 LoadBalancer 타입을 쓸 것이다.
다만 문제는 LoadBalancer의 경우 L4 계층에서 동작하므로 TCP/UDP와 같은 프로토콜을 읽을 수 있으며, HTTP와 같은 프로토콜의 정보를 세부적으로 읽을 수 없다. 그래서 L7에서 동작하는 Ingress를 통해서 외부에서 들어오는 HTTP 정보도 읽을 수 있도록 설정할 수 있다.
외부 로드 밸런서
AWS LoadBalancer Controller (Ingress Controller)가 Ingress 규칙을 파악하고, 파라미터나 annotation을 통해서 ALB(Application Load Balancer)를 생성한다. 또한 자동으로 Ingress 규칙에 따라 리스너 규칙을 설정하고 타겟 그룹을 설정한다. 그래서 자동으로 백앤드 서비스로 트래픽을 보낸다.
AWS LoadBalancer를 통하여 자동으로 모니터링, 관리, 라우팅 스케일 변경 작업 등 다양한 작업을 대신하도록 할 수 있다. 또한 DDoS 공격으로 부터 보호나 인증과 같은 작업도 효율적으로 할 수 있게된다.
내부 리버스 프록시
해당 기능은 외부의 로드밸런서로 부터 요청을 받도록 내부에 L7 리버스 프록시(예를 들어 nginx)를 두는 방식이다. 해당 L7 리버스 프록시의 설정 및 관리 등은 모두 인프라 담당자가 관리해야 해서 운영 부담이 있다.
가장 대표적인게 Nginx Ingress Controller를 사용하는 것이다.
EKS의 Ingress의 Target Type에 따른 동작
해당 내용은 지기님의 블로그에서 본 내용을 정리했다.
포스팅에서는 대상 그룹에서 Instance와 IP로 지정함에 따른 iptables 변화를 살펴보고 효율적인 것은 무엇인지 알아보는 것이다.
일단 사용할 리소스를 먼저 배포한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-test-deploy
labels:
app: test-ingress
spec:
replicas: 3
selector:
matchLabels:
app: test-ingress
template:
metadata:
labels:
app: test-ingress
spec:
containers:
- name: test-ingress
image: traefik/whoami
---
apiVersion: v1
kind: Service
metadata:
name: ingress-test-service
spec:
selector:
app: test-ingress
ports:
- port: 80
targetPort: 80
protocol: TCP
type: NodePort
이제 Ingress를 배포할 건데 여기서는 두 가지 방식으로 비교한다.
Target이 Instance인 경우
먼저 Instance로 확인해보자.
각 체인의 정책에 따라 트래픽이 흐르면서 pod로 접근하게 된다. 먼저 외부에서 호출하게되면 iptables의 PREROUTING 체인의 정책으로 시작한다.
kube-proxy를 통해서 iptables를 관리하는데 pod가 추가될때마다 정책이 iptables 정책이 계속 추가되게 된다. MSA 특성상 수 많은 서비스와 컨테이너가 존재하게 될텐데 이는 필연적으로 수 많은 정책을 만든다. 추후에는 이로 인해 모든 정책을 검토하느라 네트워크에 이슈가 생길 수 있다.
Ingress 정책 설정시 target-type을 instance로 설정해보자.
AWS LoadBalancer Controller를 통해서 자동으로 AWS ALB를 생성하고 targetgroup binding을 시작한다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: instance
spec:
ingressClassName: alb
rules:
- http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: ingress-test-service
port:
number: 80
실제로 생성된 정보를 확인하면 우리가 올린 서비스는 80포트로 올라갔지만 등록된 포트는 노드포트임을 확인 할 수 있다.
Instance 타입으로 하는 경우 ALB에서 각 instance를 target으로 DNAT하기 때문에 서비스 포트가 노드포트의 포트로 타겟이 생성된다.
이런 노트 포트로 들어온 트래픽은 모든 워커 노드가 리스닝 하고 있다가 트래픽을 등록된 Service에 보내기 위해서 iptables를 계속해서 추가한다.
이는 그냥 nodeport로 전송되는 것과 동일하다.
실제로 트래픽을 따라가보면 다음과 같다.
Target이 IP인 경우
이번에는 target-type을 ip로 변경하고 진행하고 나머지 코드는 모두 동일하다.
alb.ingress.kubernetes.io/target-type: ip
먼저 타겟 그룹을 확인해보면 포트 정보에서 실제 pod로 IP와 port로 등록된 것을 확인할 수 있다.
이는 실제 파드로 바로 트래픽이 전송되기 때문에 이렇게 설정된다. 이는 VPC CNI의 특성인데, pod가 노드와 동일한 VPC 내의 같은 CIDR에서 존재하기 때문에 별도의 NAT 과정이 필요없기 때문이다.
또한 instance 타입은 모든 instance가 붙었는데 ip 타입의 경우 정확하게 해당되는 pod만 생성된 것을 확인할 수 있다.
그럼 이제 ingress로 요청을 해보자.
이번에 유입된 시점에는 iptables의 체인에 적용되지 않은 것을 확인할 수 있다.
이로써 ingress로 ALB를 사용하고 싶다면 IP type으로 사용하는게 iptables에 대한 부하를 줄여줄 수 있다는 것을 확인할 수 있다.
API Gateway
쿠버네티스에서 현재 베타로 제공하고 있는 기능이다. Service와 Ingress 외에도 애플리케이션을 노출할 수 있는 방법 중에 하나이다.
GatewayClass : Ingress의 Ingress Class와 유사하다. API 객체를 처리하는 컨트롤러이다.
Gateway : Ingress와 작동방식이 유사한데, 진입점을 정의하고 Ingress 컨트롤러와 게이트웨이 정의를 기반으로 로드밸런싱 구성 요소 생성을 트리거 한다.
HTTPRoute(TLS,TCP,UDP 포함) : 게이트웨이 뒤에 있는 서비스에 연결하는 라우팅 규칙을 정의하고 호스트, 헤더, 경로를 기반으로 트래픽을 일치시키고 가중치에 따라 분배한다.
ReferencePolicy : 어떤 게이트웨이를 통해 어떤 서비스를 노출할 수 있는는지 제어할 수 있다.
이상으로 ingress와 apigateway에 대해서 알아보았다.