[Kubernetes] EKS에서 로드밸런싱 사용하기 (NLB, ALB)
기능 | Application Load Balancer | Network Load Balancer | Classic Load Balancer |
로드 밸런서 유형 | 계층 7 | 계층 4 | 계층 4/7 |
대상 유형 | IP, 인스턴스, Lambda | IP, 인스턴스, ALB | |
흐름/프록시 동작 종료 | 예 | 예 | 예 |
프로토콜 리스너 | HTTP, HTTPS, gRPC | TCP, UDP, TLS | TCP, SSL/TLS, HTTP, HTTPS |
다음을 통해 연결 가능 | VIP | VIP |
🚀 NLB for LoadBalancer Service
Amazon EKS의 네트워크 로드 밸런싱 - Amazon EKS
eks에서 로드밸런서를 생성하면 기본적으로 classic
LoadBalancer가 생성된다.
EC2 인스턴스를 사용하는 경우 classic
LoadBalancer는 정상 작동하지만 Fargate
를 사용하는 경우에는 classic
LoadBalancer가 작동하지 않는다.classic
LoadBalancer는 반드시 EC2 인스턴스에만 연결될 수 있는데 Fargate 같은 경우 EC2 인스턴스가 생성되지 않기 때문이다.
📌 EC2 인스턴스에 NLB 설정하기
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"
로드밸런서를 만들 때 annotation
을 붙여야한다.
external
은 외부용이라는 의미이며 nlb-target-type
은 NLB
가 생성되고 NLB
의 타겟이되는 대상은 인스턴스라는 의미이다.
정확히는 EC2 인스턴스의 NodePort
가 타겟이 된다. 로드밸런서 서비스는 NodePort
를 사용한다.
그리고 EC2 인스턴스 내부에 파드가 존재하며 파드 안에는 App이 실행되고 있다.
즉, NLB
를 통해 파드 내의 App에 부하 분산한다.
📌 Fargate에 NLB 설정하기
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
다음은 Fargate를 위한 aws-load-balancer-nlb-target-type
이다.
ip
타입은 파드에 NLB
가 직접적으로 연결되는 방식이다.
즉, Fargate
에 사용하기 위해 만들어 놓은 것이다.
인스턴스가 private network에 배치되었으므로 퍼블릭 ip를 가지지 않는다.
private 서브넷에 배치되어있다.
myapp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myweb-deploy
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: myweb
image: ghcr.io/c1t1d0s7/go-myweb
ports:
- containerPort: 8080
mysvc.yaml
apiVersion: v1
kind: Service
metadata:
name: myweb-svc-lb
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"
spec:
type: LoadBalancer
selector:
app: web
ports:
- port: 80
targetPort: 8080
annotations
를 붙인다.
PS C:\Users\Shinsohui\aws-eks\nlb> kubectl get deploy,rs,po,svc,ep
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/myweb-deploy 3/3 3 3 19s
NAME DESIRED CURRENT READY AGE
replicaset.apps/myweb-deploy-657f957c85 3 3 3 19s
NAME READY STATUS RESTARTS AGE
pod/myweb-deploy-657f957c85-4mlzw 1/1 Running 0 18s
pod/myweb-deploy-657f957c85-sxhcz 1/1 Running 0 18s
pod/myweb-deploy-657f957c85-z9xws 1/1 Running 0 18s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 40m
service/myweb-svc-lb LoadBalancer 10.100.103.31 <pending> 80:30785/TCP 14s
NAME ENDPOINTS AGE
endpoints/kubernetes 192.168.133.118:443,192.168.97.133:443 40m
endpoints/myweb-svc-lb 192.168.131.98:8080,192.168.167.43:8080,192.168.99.189:8080 14s
PS C:\Users\Shinsohui\aws-eks\nlb> kubectl describe svc myweb-svc-lb
Name: myweb-svc-lb
Namespace: default
Labels: <none>
Annotations: service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: instance
service.beta.kubernetes.io/aws-load-balancer-type: external
🚀 AWS LoadBalancer Controller 설치
AWS Load Balancer Controller 추가 기능 설치 - Amazon EKS
NLB
나 ALB
를 구성하기 위해서는 다음 addon를 추가해야한다.
eksctl create iamserviceaccount \
--cluster=my-cluster \
--namespace=kube-system \
--name=aws-load-balancer-controller \
--attach-policy-arn=arn:aws:iam::111122223333:policy/AWSLoadBalancerControllerIAMPolicy \
--override-existing-serviceaccounts \
--approve
eksctl
또는 kubectl
을 사용하여 IAM 역할을 생성하고 AWS 로드 밸런서 컨트롤러의 kube-system
네임스페이스에 aws-load-balancer-controller
라는 쿠버네티스 서비스 계정을 추가해야한다.
helm repo add eks https://aws.github.io/eks-charts
helm repo update
레포지토리를 추가하고 업데이트한다.
helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=myeks-custom --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller --set image.repository=602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon/aws-load-balancer-controller
PS C:\Users\Shinsohui\aws-eks\nlb> helm list -n kube-system
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
aws-load-balancer-controller kube-system 1 2022-06-01 00:05:35.7677369 +0900 KST deployed aws-load-balancer-controller-1.4.2 v2.4.2
PS C:\Users\Shinsohui\aws-eks\nlb> kubectl get po -A
NAMESPACE NAME READY STATUS RESTARTS AGE
default myweb-deploy-657f957c85-4mlzw 1/1 Running 0 18m
default myweb-deploy-657f957c85-sxhcz 1/1 Running 0 18m
default myweb-deploy-657f957c85-z9xws 1/1 Running 0 18m
kube-system aws-load-balancer-controller-5d9867ff4d-c5lvr 1/1 Running 0 29s
kube-system aws-load-balancer-controller-5d9867ff4d-hhwwk 1/1 Running 0 29s
kube-system aws-node-57llb 1/1 Running 0 45m
kube-system aws-node-kbjx5 1/1 Running 0 45m
kube-system aws-node-mscqs 1/1 Running 0 45m
kube-system coredns-556f6dffc4-k5s79 1/1 Running 0 58m
kube-system coredns-556f6dffc4-zx2lc 1/1 Running 0 58m
kube-system kube-proxy-68rw9 1/1 Running 0 45m
kube-system kube-proxy-gl9s6 1/1 Running 0 45m
kube-system kube-proxy-k89dw 1/1 Running 0 45m
PS C:\Users\Shinsohui\aws-eks\nlb> kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 58m
myweb-svc-lb LoadBalancer 10.100.103.31 k8s-default-mywebsvc-1771186f98-1a8bcf2f87e5c446.elb.ap-northeast-2.amazonaws.com 80:30785/TCP 18m
network
타입의 로드 밸런서가 생성되었다.
EC2 인스턴스 기반의 EKS는 classic
이나 network
모두 정상 작동하지만 Fargate
의 경우 classic
유형이 연결될 수 없다고 했다. → 그렇기 때문에 반드시 NLB
로 구성해야 한다.
Schema가 internal
이라는 것은 내부용으로 사용한다는 것이다.
public network에 배치된 것이 아니므로 외부에서 접속할 수 없다.
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
internet-facing
을 사용해야 public network에 배치된다.
현재 NLB
는 private network에 배치되어있다.
외부에 노출이 된 것이 아니기 때문에 다른 내부 서비스에서만 사용할 수 있다.
apiVersion: v1
kind: Service
metadata:
name: myweb-svc-lb
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
spec:
type: LoadBalancer
selector:
app: web
ports:
- port: 80
targetPort: 8080
최종 코드는 다음과 같다.
internet-facing
로 변경되었고 활성되었다.
외부에서 접속 가능하다.
🚀 Ingress for ALB
Amazon EKS의 애플리케이션 로드 밸런싱 - Amazon EKS
L7에서 애플리케이션 트래픽을 로드 밸런싱하려면 Kubernetes ingress
를 배포해야한다. 이는 AWS Application Load Balancer를 프로비저닝한다.
Ingress
도 마찬가지로 AWS LoadBalancer Controll
이 설치되어 있어야 한다.
- alb.ingress.kubernetes.io/target-type: ip -
Fargate
용 - alb.ingress.kubernetes.io/target-type: ip -
EC2
용
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myweb-ing
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/target-type: instance
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myweb-svc-lb
port:
number: 80
PS C:\Users\Shinsohui\aws-eks\nlb> kubectl get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
myweb-ing <none> * internal-k8s-default-mywebing-ba340b948e-1254008606.ap-northeast-2.elb.amazonaws.com 80 4s
Ingress
의 주소가 배치되었다.
프로비저닝 중인 ALB를 확인할 수 있다.
해당 ALB도 마찬가지로 Schema가 internal
이다. 외부에서 사용하기 위해서는 annotations
을 조정해야 한다.
internal-facing
으로 변경되었다.
이제 외부에서 접속 가능하다.