IT기술/쿠버네티스 (k8s)

RKE2 인그레스 완벽 가이드: 외부 트래픽 라우팅과 로드밸런서 구축

후스파 2025. 7. 16. 18:51
반응형

쿠버네티스 클러스터에 외부 트래픽을 라우팅하려면 인그레스(ingress) 컨트롤러와 로드밸런서 설정이 필요합니다. RKE2는 기본적으로 ingress-nginx를 DaemonSet 형태로 제공하지만, 로드밸런서 서비스 타입으로 변경하여 외부 IP를 할당받거나 MetalLB 같은 베어메탈 로드밸런서를 연동할 수 있습니다.


RKE2에서 인그레스의 개요

RKE2는 기본적으로 Ingress-NGINX 컨트롤러를 DaemonSet으로 배포하여 호스트 네트워킹을 사용합니다. 이는 베어메탈 환경에서는 이상적이지만, 클라우드 네이티브 환경에서 LoadBalancer를 통한 인그레스에는 적합하지 않습니다.

RKE2 Ingress-NGINX의 핵심 특징

  • 사전 구성 및 관리: RKE2가 자동으로 Ingress-NGINX 컨트롤러의 라이프사이클을 관리
  • 클러스터 인식 구성: 클러스터의 네트워킹 설정에 맞춘 기본값 제공
  • HelmChart CRD 통합: HelmChart 커스텀 리소스를 통한 간편한 업그레이드 및 구성 변경
  • 기본 IngressClass: ingress-nginx가 시스템 기본 인그레스 클래스로 구성

아키텍처 구성 요소

  • Ingress Resource: HTTP/HTTPS 트래픽을 백엔드 서비스로 라우팅하는 규칙 정의
  • Ingress-NGINX Controller Pod: Ingress 정의에 따라 라우팅을 관리하고 NGINX를 구성
  • Load Balancer Integration: 클라우드 로드밸런서 또는 외부 로드밸런서와의 통합

Ingress-NGINX 컨트롤러 배포하기

기본 배포 확인

# 기본 DaemonSet 확인
kubectl -n kube-system get daemonset ingress-nginx

# 인그레스 컨트롤러 상태 확인
kubectl -n kube-system get pods -l app.kubernetes.io/name=ingress-nginx

# 기본 서비스 확인
kubectl -n kube-system get svc -l app.kubernetes.io/name=ingress-nginx

호스트 네트워크로 동작하는 인그레스-엔진엑스(DaemonSet)가 보이면 기본 배포가 완료된 상태입니다.

Deployment 및 LoadBalancer 서비스로 변경

RKE2가 /var/lib/rancher/rke2/server/manifests 디렉토리의 매니페스트를 자동으로 적용하므로, 이곳에 HelmChartConfig를 생성하면 됩니다.

# HelmChartConfig 생성
cat <<EOF | sudo tee /var/lib/rancher/rke2/server/manifests/ingress-nginx.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: rke2-ingress-nginx
  namespace: kube-system
spec:
  valuesContent: |-
    controller:
      hostNetwork: false
      kind: Deployment
      replicaCount: 3
      service:
        enabled: true
        type: LoadBalancer
        annotations:
          service.beta.kubernetes.io/aws-load-balancer-type: "nlb"  # AWS의 경우
      config:
        use-forwarded-headers: "true"
        enable-real-ip: "true"
        proxy-real-ip-cidr: "0.0.0.0/0"
      metrics:
        enabled: true
        service:
          annotations:
            prometheus.io/scrape: "true"
            prometheus.io/port: "10254"
      resources:
        requests:
          cpu: 100m
          memory: 90Mi
        limits:
          cpu: 500m
          memory: 500Mi
EOF

변경사항 확인

# 배포 상태 확인
kubectl -n kube-system get deploy,svc -l app.kubernetes.io/name=ingress-nginx

# LoadBalancer IP 할당 확인
kubectl -n kube-system get svc ingress-nginx-controller

# 인그레스 컨트롤러 로그 확인
kubectl -n kube-system logs -l app.kubernetes.io/name=ingress-nginx -f

위 설정으로 ingress-nginx가 Deployment로 재배포되며, LoadBalancer 타입의 서비스가 생성됩니다.


MetalLB를 이용한 LoadBalancer 구축

베어메탈 환경에서는 클라우드 로드밸런서가 없어 MetalLB를 사용해 외부 IP 풀을 할당해야 합니다.

MetalLB 설치

# MetalLB 최신 버전 설치
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.3/config/manifests/metallb-native.yaml

# 네임스페이스 생성 (이미 존재할 수 있음)
kubectl create namespace metallb-system --dry-run=client -o yaml | kubectl apply -f -

# memberlist secret 생성
kubectl -n metallb-system create secret generic memberlist \
  --from-literal=secretkey="$(openssl rand -base64 128)" \
  --dry-run=client -o yaml | kubectl apply -f -

# MetalLB 컨트롤러 상태 확인
kubectl -n metallb-system get pods

IP 풀 설정

MetalLB가 사용할 IP 대역을 정의합니다.

cat <<EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: production-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.100.200-192.168.100.210  # 환경에 맞게 조정
  autoAssign: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: production-l2
  namespace: metallb-system
spec:
  ipAddressPools:
  - production-pool
  interfaces:
  - eth0  # 네트워크 인터페이스 지정
EOF

BGP 모드 설정 (선택사항)

# BGP 모드를 위한 설정 (고급 네트워킹 환경)
cat <<EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: peer1
  namespace: metallb-system
spec:
  myASN: 64500
  peerASN: 64501
  peerAddress: 192.168.1.1
---
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
  name: bgp-adv
  namespace: metallb-system
spec:
  ipAddressPools:
  - production-pool
EOF

대역은 클러스터 네트워크 환경에 맞춰 조정합니다.


서비스 및 인그레스 실습 예제

Nginx 배포 및 서비스

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-nginx
  namespace: default
  labels:
    app: sample-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample-nginx
  template:
    metadata:
      labels:
        app: sample-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25-alpine
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 50m
            memory: 64Mi
          limits:
            cpu: 100m
            memory: 128Mi
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: sample-nginx-svc
  namespace: default
spec:
  selector:
    app: sample-nginx
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
  type: ClusterIP  # Ingress를 통해 노출할 경우 ClusterIP 사용
EOF

인그레스 리소스 작성

cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: sample-nginx-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
spec:
  ingressClassName: nginx
  rules:
  - host: sample.mycluster.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: sample-nginx-svc
            port:
              number: 80
  - host: nginx.example.com  # 추가 호스트
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: sample-nginx-svc
            port:
              number: 80
EOF

TLS/SSL 인그레스 설정

# TLS 인증서 생성 (자체 서명)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt \
  -subj "/CN=sample.mycluster.local/O=sample.mycluster.local"

# TLS Secret 생성
kubectl create secret tls sample-tls \
  --key tls.key --cert tls.crt

# HTTPS 인그레스 설정
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: sample-nginx-tls-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - sample.mycluster.local
    secretName: sample-tls
  rules:
  - host: sample.mycluster.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: sample-nginx-svc
            port:
              number: 80
EOF

host 설정을 /etc/hosts에 매핑하거나 DNS로 연결한 뒤 http://sample.mycluster.local 접속 테스트를 진행합니다.


외부 접속 확인 및 테스트

서비스 상태 확인

# LoadBalancer IP 확인
kubectl get svc -A | grep LoadBalancer

# 인그레스 상태 확인
kubectl get ingress -A

# 인그레스 상세 정보 확인
kubectl describe ingress sample-nginx-ingress

# 엔드포인트 확인
kubectl get endpoints sample-nginx-svc

연결 테스트

# LoadBalancer IP로 직접 접속 테스트
EXTERNAL_IP=$(kubectl -n kube-system get svc ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl -H "Host: sample.mycluster.local" http://$EXTERNAL_IP

# /etc/hosts 설정 후 도메인으로 접속
echo "$EXTERNAL_IP sample.mycluster.local" | sudo tee -a /etc/hosts
curl http://sample.mycluster.local

# HTTPS 테스트 (TLS 설정한 경우)
curl -k https://sample.mycluster.local

트러블슈팅

# 인그레스 컨트롤러 로그 확인
kubectl -n kube-system logs -l app.kubernetes.io/name=ingress-nginx --tail=100

# 인그레스 컨트롤러 설정 확인
kubectl -n kube-system exec -it deployment/ingress-nginx-controller -- nginx -T

# 서비스 디스커버리 확인
kubectl -n kube-system exec -it deployment/ingress-nginx-controller -- nslookup sample-nginx-svc.default.svc.cluster.local

# 포트 포워딩으로 직접 테스트
kubectl port-forward svc/sample-nginx-svc 8080:80
curl http://localhost:8080

고급 인그레스 설정

다중 백엔드 및 경로 기반 라우팅

cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-service-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /api/v1(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: api-v1-service
            port:
              number: 8080
      - path: /api/v2(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: api-v2-service
            port:
              number: 8080
      - path: /web(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
EOF

레이트 리미팅 및 인증

cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: protected-ingress
  annotations:
    nginx.ingress.kubernetes.io/rate-limit: "10"
    nginx.ingress.kubernetes.io/rate-limit-window: "1m"
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required'
spec:
  ingressClassName: nginx
  rules:
  - host: protected.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: protected-service
            port:
              number: 80
EOF

# Basic Auth Secret 생성
htpasswd -c auth admin
kubectl create secret generic basic-auth --from-file=auth

마무리

이 가이드에서는 RKE2에서 기본 DaemonSet 형태의 ingress-nginx를 Deployment로 전환하고 LoadBalancer 서비스로 노출하는 방법, MetalLB를 이용한 외부 IP 풀 설정, 실제 Nginx 예제 배포 및 인그레스 리소스 적용까지 실습했습니다. 베어메탈 환경에서도 MetalLB와 HelmChartConfig를 통해 클라우드와 유사한 외부 트래픽 라우팅을 구현할 수 있으니, 이를 토대로 운영 환경에 맞게 확장해 보시기 바랍니다.
핵심 포인트:

  • RKE2 기본 제공 Ingress-NGINX를 HelmChartConfig로 커스터마이징
  • DaemonSet에서 Deployment로 전환하여 확장성 향상
  • MetalLB 통합으로 베어메탈 환경에서 LoadBalancer 구현
  • TLS/SSL 지원으로 보안 강화
  • 고급 라우팅 규칙으로 복잡한 애플리케이션 구조 지원

RKE2의 통합된 Ingress-NGINX 컨트롤러를 통해 클라우드와 온프레미스 환경 모두에서 안정적이고 확장 가능한 외부 트래픽 라우팅을 구현할 수 있습니다.

반응형