파드는 각각 고유한 IP를 가지지만, 새로운 파드가 생성되거나 재시작될 때마다 IP가 변경됩니다.
이로 인해 다른 Pod 또는 외부에서 특정 Pod에 안정적으로 접근하는 것이 어렵습니다.
이를 해결하기 위해 Kubernetes는 여러 파드를 하나의 단일 엔드포인트로 묶어주는 "Service"를 제공합니다.
Service를 사용하면 파드가 변경되더라도 항상 일정한 네트워크 주소를 유지하며, 로드 밸런싱을 통해 트래픽을 여러 Pod으로 자동 분산할 수 있습니다.
Serivce의 종류
▷ ClusterIP
클러스터 내부에서만 접근 가능하며, 클러스터 내부의 다른 파드들만 사용할 수있습니다. (도메인(DNS) 기반으로도 접근 가능)
kube-proxy가 iptables을 이용해 트래픽을 적절한 파드로 전달합니다.
▷ NodePort
클러스터 외부에서도 접근할 수 있도록 각 노드의 특정 포트를 개방하고 트래픽은 해당 포트를 통해 내부의 파드로 전달됩니다. iptables가 트래픽을 적절한 파드로 전달합니다.
▷ LoadBalancer
AWS LoadBalancer를 통해 트래픽을 클러스터의 여러 노드로 분산하며, 이 후 iptables가 파드로 전달합니다.
AWS LoadBalancer Controller를 함께 설정해주어야 합니다.
Cloud Controller Manager를 통해 k8s NodePort 정보를 기반으로 CLB/NLB를 자동 프로비저닝
AWS LoadBalancer Controller는 EKS 환경에서 AWS의 LoadBalancer(ALB/NLB)와 자동으로 연결해주는 컨트롤러입니다.
iptables 정책 적용 순서: PREROUTING → KUBE-SERVICES → KUBE-SVC-### → KUBE-SEP-#<파드1> , KUBE-SEP-#<파드2> , KUBE-SEP-#<파드3>
Ingress
클러스터 내부의 여러 서비스(NodePort, ClusterIP, LoadBalancer)를 Web Proxy처럼 동작하여 HTTP/HTTPS로 외부에 노출하는 역할을 합니다.
실습을 위한 서비스, 게임 파드, 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
#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'}"
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 레코드가 생성됩니다.
4주차 Study - EKS Observability (0) | 2025.03.01 |
---|---|
3주차 Study - EKS Storage, Managed Node Groups (0) | 2025.02.21 |
2주차 Study - EKS Networking (1) (1) | 2025.02.15 |
2주차 Study - EKS Networking (실습 환경 구축) (0) | 2025.02.15 |
1주차 Study - EKS 클러스터 배포 (0) | 2025.02.07 |