상세 컨텐츠

본문 제목

2주차 Study - EKS Networking (2)

[AWS]/[EKS]

by scdo 2025. 2. 15. 19:45

본문

Service

파드는 각각 고유한 IP를 가지지만, 새로운 파드가 생성되거나 재시작될 때마다 IP가 변경됩니다.
이로 인해 다른 Pod 또는 외부에서 특정 Pod에 안정적으로 접근하는 것이 어렵습니다.

이를 해결하기 위해 Kubernetes는 여러 파드를 하나의 단일 엔드포인트로 묶어주는 "Service"를 제공합니다.
Service를 사용하면 파드가 변경되더라도 항상 일정한 네트워크 주소를 유지하며, 로드 밸런싱을 통해 트래픽을 여러 Pod으로 자동 분산할 수 있습니다.

 

Serivce의 종류

▷ ClusterIP

클러스터 내부에서만 접근 가능하며, 클러스터 내부의 다른 파드들만 사용할 수있습니다. (도메인(DNS) 기반으로도 접근 가능)

kube-proxy가  iptables을 이용해 트래픽을 적절한 파드로 전달합니다.

출처 - AWS

▷ NodePort

클러스터 외부에서도 접근할 수 있도록 각 노드의 특정 포트를 개방하고 트래픽은 해당 포트를 통해 내부의 파드로 전달됩니다. iptables가 트래픽을 적절한 파드로 전달합니다.

 

출처

LoadBalancer

AWS LoadBalancer를 통해 트래픽을 클러스터의 여러 노드로 분산하며, 이 후 iptables가 파드로 전달합니다.

AWS LoadBalancer Controller를 함께 설정해주어야 합니다.

출처

 

Cloud Controller Manager를 통해 k8s NodePort 정보를 기반으로 CLB/NLB를 자동 프로비저닝

 

 

AWS LoadBalancer Controller는 EKS 환경에서 AWS의 LoadBalancer(ALB/NLB)와 자동으로 연결해주는 컨트롤러입니다.

AWS LoadBalancerController + NLB IP 모드 동작 원리 - 출처:

 

iptables 정책 적용 순서: PREROUTING → KUBE-SERVICES → KUBE-SVC-### → KUBE-SEP-#<파드1> ,  KUBE-SEP-#<파드2> ,  KUBE-SEP-#<파드3>

트래픽 예제 흐름

 

Ingress

클러스터 내부의 여러 서비스(NodePort, ClusterIP, LoadBalancer)를 Web Proxy처럼 동작하여 HTTP/HTTPS로 외부에 노출하는 역할을 합니다.

AWS LoadBalancerController + ALB IP 모드 동작 원리 - 출처

 

실습을 위한 서비스, 게임 파드, Ingress 배포합니다.

# 게임 파드와 Service, Ingress 배포
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
  name: game-2048
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: game-2048
  name: deployment-2048
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: app-2048
  replicas: 2
  template:
    metadata:
      labels:
        app.kubernetes.io/name: app-2048
    spec:
      containers:
      - image: public.ecr.aws/l6m2t8p7/docker-2048:latest
        imagePullPolicy: Always
        name: app-2048
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  namespace: game-2048
  name: service-2048
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: NodePort
  selector:
    app.kubernetes.io/name: app-2048
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: game-2048
  name: ingress-2048
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: service-2048
              port:
                number: 80
EOF
#배포 확인
kubectl get ingress,svc,ep,pod -n game-2048
kubectl get-all -n game-2048
kubectl get targetgroupbindings -n game-2048

확인 결과
watch 명령어로 모니터링

#ALB 생성 확인
aws elbv2 describe-load-balancers --query 'LoadBalancers[?contains(LoadBalancerName, `k8s-game2048`) == `true`]' | jq

#명령어를 쉽게 사용하기 위해 변수 설정
ALB_ARN=$(aws elbv2 describe-load-balancers --query 'LoadBalancers[?contains(LoadBalancerName, `k8s-game2048`) == `true`].LoadBalancerArn' | jq -r '.[0]')

변수 설정 후 명령어 실행

 

#변수 설정
TARGET_GROUP_ARN=$(aws elbv2 describe-target-groups --load-balancer-arn $ALB_ARN | jq -r '.TargetGroups[0].TargetGroupArn')

#타겟 그룹 상태 조회
aws elbv2 describe-target-health --target-group-arn $TARGET_GROUP_ARN | jq

타겟 상태 확인

#Ingress 확인
kubectl get ingress -n game-2048 ingress-2048 -o jsonpath="{.status.loadBalancer.ingress[*].hostname}{'\n'}"

Ingress 확인

 

접속 확인

AWS 콘솔에서 ALB의 대상 그룹에 등록된 대상 확인합니다.

리소스 맵

 

ExternalDNS

ExternalDNS는 Kubernetes 서비스 및 인그레스(Ingress)의 DNS 레코드를 자동으로 외부 DNS에 등록하는 컨트롤러입니다.
즉, Kubernetes 내부 서비스에 자동으로 퍼블릭 DNS 레코드를 생성하여 외부에서도 접근할 수 있도록 합니다.

참고

참고: ExternalDNS에서 AWS Route 53을 관리하기 위한 방법 3가지: Node IAM Role, Static Credentials, IRSA (IAM Roles for Service Accounts) 

 

AWS Route 53 정보 확인(Public 도메인 소유 필요)

#변수 지정
MyDomain=sc-do.com
#자신의 Route 53 도메인 ID 조회
aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." | jq
aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Name"
aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Id" --output text

#변수 지정
MyDnzHostedZoneId=`aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Id" --output text`
echo $MyDnzHostedZoneId

 

ExternalDNS 설치

# 변수 확인
echo $MyDomain, $MyDnzHostedZoneId

 

#ExternalDNS 배포
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/aews/externaldns.yaml
cat externaldns.yaml
MyDomain=$MyDomain MyDnzHostedZoneId=$MyDnzHostedZoneId envsubst < externaldns.yaml | kubectl apply -f -

# 확인 및 로그 모니터링
kubectl get pod -l app.kubernetes.io/name=external-dns -n kube-system
kubectl logs deploy/external-dns -n kube-system -f

 

Service(NLB) + 도메인 연동(ExternalDNS)

# 테트리스 디플로이먼트 배포
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tetris
  labels:
    app: tetris
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tetris
  template:
    metadata:
      labels:
        app: tetris
    spec:
      containers:
      - name: tetris
        image: bsord/tetris
---
apiVersion: v1
kind: Service
metadata:
  name: tetris
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
    #service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "80"
spec:
  selector:
    app: tetris
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  type: LoadBalancer
  loadBalancerClass: service.k8s.aws/nlb
EOF

배포 확인

# NLB에 ExternanDNS 로 도메인 연결
kubectl annotate service tetris "external-dns.alpha.kubernetes.io/hostname=tetris.$MyDomain"
#확인
aws route53 list-resource-record-sets --hosted-zone-id "${MyDnzHostedZoneId}" --query "ResourceRecordSets[?Type == 'A']" | jq

연결 확인

# 도메인 체크
echo -e "My Domain Checker Site1 = https://www.whatsmydns.net/#A/tetris.$MyDomain"
echo -e "My Domain Checker Site2 = https://dnschecker.org/#A/tetris.$MyDomain"

# 웹 접속 주소 확인 및 접속
echo -e "Tetris Game URL = http://tetris.$MyDomain"

웹브라우저로 접속

#리소스 삭제
#삭제 시 externaldns 에 의해서 A레코드도 같이 삭제됨
kubectl delete deploy,svc tetris

 

CoreDNS

CoreDNS는 Kubernetes 클러스터에서 DNS(Domain Name System) 요청을 처리하는 기본 네트워크 서비스로 
Kubernetes에서는 서비스나 파드 간에 이름으로 통신해야 하는데, 이를 처리하는 게 CoreDNS입니다.

클러스터에서 서비스와 파드가 생성되면 자동으로 이에 대한 DNS 레코드가 생성됩니다.

Kubernetes DNS 동작

  • Pod 내 애플리케이션(Application)이 DNS 조회 요청을 보냄
  • Pod의 DNS Resolver가 /etc/resolv.conf에 설정된 DNS 서버를 참조하여 요청을 전송
  • 요청이 nodelocaldns(로컬 DNS 캐시)를 거쳐 CoreDNS로 전달됨
  • CoreDNS가 Kubernetes API에서 서비스(Service)와 엔드포인트(Endpoints) 정보를 조회하여 응답 생성
  • CoreDNS에 해당 요청이 없으면, 노드의 /etc/resolv.conf에 지정된 외부 DNS 서버로 포워딩

관련글 더보기