AWS EKS에 ALB를 이용해 여러 서비스 연결하기

2023. 4. 22. 16:23Dev/EKS

728x90

이 글은 AWS EKS에서 한 개의 로드밸런서(ALB)에 여러 서비스를 연결하는 방법을 설명합니다.
  One LoadBalancer - Multi Service (Application)

EKS + ALB

AWS EKS 클러스터 생성과 AWS Load Balancer Controller 설치는 이전 글을 참고하세요.

https://nauco.tistory.com/89

 

EKS에 CLB, NLB, ALB 만들기, AWS Load Balancer Controller 사용

AWS EKS에서 AWS Load Balancer Controller를 사용해 CLB(Classic Load Balancer), NLB(Network Load Balancer), ALB(Application Load Balancer)를 만들어 보겠습니다. AWS Load Balancer Controller란? Elastic Load Balancer를 Kubernetes cluster에서

nauco.tistory.com

 

하나의 LB에 하나의 서비스를 연결하는 예제는 많습니다.

하지만 실제 업무에서는 하나의 로드밸런서에 여러 서비스(애플리케이션)를 연결하는 경우가 더 많습니다.

로드밸런서를 여러 개 두는 게 더 내구성이 좋겠지만
AWS Elastic Loadbalancer는 굉장히 튼튼하고, 또 그만큼 비용이 들기 때문입니다.


이 글에서는 한 개의 ALB에 다수의 애플리케이션을 연결하는 방법을 소개하면서,
ALB의 이름 설정, ALB에 연결되는 타겟그룹의 이름 생성 규칙, 우선순위, 하위 경로에서 애플리케이션 동작 결과 등을 설명합니다.

 

아래 코드를 기반으로 조금씩 수정해서 사용했습니다.

이전 글에서는 deployment에서 kodekloud/webapp-color 이미지를 사용했는데

이 글에서는 하위 경로에 대한 웹앱의 결과가 필요합니다.
위 앱의 소스를 약간 수정해서 hodong42/flask 이미지를 새로 만들어서 사용했습니다.

소스는 https://github.com/nauco/flask 에서 확인할 수 있습니다.

 

첨부한 yaml파일 red.yaml, blue.yaml을 apply 한 결과입니다.

k get po,ing
NAME                                   READY   STATUS    RESTARTS   AGE
pod/deployment-blue-649cf99569-7hh5s   1/1     Running   0          12m
pod/deployment-blue-649cf99569-8xjdp   1/1     Running   0          12m
pod/deployment-blue-649cf99569-zp7hs   1/1     Running   0          12m
pod/deployment-red-58d9d8856c-clsg8    1/1     Running   0          12m
pod/deployment-red-58d9d8856c-cmx27    1/1     Running   0          12m

NAME                                     CLASS   HOSTS   ADDRESS                                                                       PORTS   AGE
ingress.networking.k8s.io/ingress-blue   alb     *       k8s-default-ingressb-70eee89a32-1797381334.ap-northeast-2.elb.amazonaws.com   80      17m
ingress.networking.k8s.io/ingress-red    alb     *       k8s-default-ingressr-90bc2ab51d-181710426.ap-northeast-2.elb.amazonaws.com    80      17m​

로드밸런서가 생성되고 서비스가 노출되면서 웹 애플리케이션을 확인하려면 약 3분 정도 소요됩니다.
새로고침을 누르면 연결된 pod의 이름이 변하는 것을 볼 수 있습니다.

위 주소 하위로 /abc, /hodong 처럼 텍스트를 입력하면
화면에서 경로에 입력한 글자를 띄워줍니다.

 

이번에는 인그레스 리소스의 paths에 경로를 추가합니다.

ingress-red에는 /blue, ingress-blue에는 /red를 추가하고 각각 서비스를 연결합니다.
경로를 바꾸거나, 연결된 서비스를 달리해서 테스트하셔도 됩니다.

Ingress에서 paths 아래 path를 각각 추가했습니다.

path 추가 후 다시 apply 해줍니다.

루트 경로가 blue인 주소입니다.

k8s-default-ingressb의 루트 경로로 호출하면 기본 blue

추가로 설정한 /red로 호출하면 red 서비스의 하위 경로

설정하지 않은 /blue로 호출하면 기본 blue 서비스의 하위 경로가 응답합니다.

 

k8s-default-ingressr도 같은 규칙으로 동작합니다.

루트 경로가 red인 주소도 예상한 결과대로 나옵니다.

 

/blue일 때 blue의 루트경로, /red일 때 red의 루트경로를 호출하려면 nginx-ingress의 rewrite옵션을 사용해야 합니다.
(다음 글로 작성할 예정입니다)

 

이제 ingress마다 로드밸런서를 만들지 않고

하나의 로드밸런서에서 경로로 애플리케이션을 분기해서 사용해 봅시다.

 

red.yaml의 ingress-red에서 group.name annotation을 추가합니다.
값은 자유롭게 쓰셔도 됩니다.

그리고 변경한 yaml을 적용합니다.

k apply -f red.yaml
deployment.apps/deployment-red unchanged
service/service-red unchanged
ingress.networking.k8s.io/ingress-red configured

ingress resource만 configured 됩니다.

ingress를 확인해 보면 새로운 주소를 확인할 수 있습니다.

k get ing
NAME           CLASS   HOSTS   ADDRESS                                                                       PORTS   AGE
ingress-blue   alb     *       k8s-default-ingressb-70eee89a32-1797381334.ap-northeast-2.elb.amazonaws.com   80      46m
ingress-red    alb     *       k8s-color-c66cd1f622-838182923.ap-northeast-2.elb.amazonaws.com               80      46m

kubernetes ingress 리소스의 AGE는 그대로지만

k8s-default-ingressr-90bc2ab51d-181710426.ap-northeast-2.elb.amazonaws.com 였던 로드밸런서는

k8s-color-c66cd1f622-838182923.ap-northeast-2.elb.amazonaws.com 로 새로 프로비저닝 되었습니다.

이름에 groupname인 color가 들어가고 dns도 새로 생성된 새로운 로드밸런서로 변경되었습니다.

 

blue.yaml의 ingress-blue에도 같은 group.name으로 어노테이션을 추가해서 적용해 보겠습니다.

k8s-default-ingressb로 시작하던 LB(ingress-blue에서 생성한)가 삭제되고
두 인그레스 리소스가 하나의 로드밸런서로 연결되었습니다.

궁금한 점이 생깁니다.
두 인그레스에서 루트 경로에 각각 서비스를 연결해 놨습니다.

이 주소에서 루트로 호출하면 블루가 열릴까? 레드가 열릴까? 랜덤으로(혹은 번갈아가며) 열릴까? 궁금합니다.

 

 

 

 

 

정답은 "블루가 열린다"입니다.

Listeners Rule의 순서는
AWS Console > EC2 > Load balancers > 생성한 로드밸런서 > Listeners > Rules에서 확인 가능합니다.

 

ingress-blue에서 설정한 /red 경로가 1순위, /* 가 2순위 (blue)
ingress-red에서 설정한 /blue 경로가 3순위, /* 가 4순위 (red)로 확인 가능합니다.

 

 

그렇다면 왜 ingress-blue의 순서가 ingress-red 보다 먼저일까요?

저는 순서를 정하는 규칙이
먼저 생성한 게 먼저 또는 나중에 생성한 게 먼저
둘 중 하나라고 생각했습니다.

위에서는 red를 먼저 적용하고, 뒤에 blue를 적용했습니다.

나중에 적용한 룰이 밀어내기 식으로 먼저 앞선 우선순위를 가진다고 예상하고 이를 검증하기 위해 테스트를 해보았습니다.

kubectl delete ing ingress-red
명령어로 ingress-red를 지웁니다.

yaml파일로 지우면 서비스와 디플로이먼트까지 지워지니 ingress 리소스만 직접 지웠습니다.

로드밸런서는 지워지지 않고 예상대로 룰만 3개로 줄었습니다.

 

테스트를 위해 ingress-red의 하위경로 룰을 /blue에서 /yellow로 바꿔서 다시 apply 했습니다.

 

이번에도 ingress-blue가 먼저, ingress-red가 나중입니다.
생성 순서와 룰의 순서는 상관이 없다는 것을 알 수 있습니다.

 

ingress에서 만드는 listener rules의 순서가 정해지는 규칙순서를 직접 정하는 방법 모두 공식 문서에서 확인할 수 있습니다.

group.order annotation을 사용하면 규칙의 순서를 정할 수 있고,
숫자가 작은 순서가 먼저 적용되며, 순서를 정하지 않으면 0으로 설정
같은 순서를 가지면 ingress 리소스의 namespace/name 의 사전식 순서로 정렬됩니다.

https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.5/guide/ingress/annotations/#ingressgroup

 

Annotations - AWS Load Balancer Controller

Ingress annotations You can add annotations to kubernetes Ingress and Service objects to customize their behavior. Annotation keys and values can only be strings. Advanced format should be encoded as below: boolean: 'true' integer: '42' stringList: s1,s2,s

kubernetes-sigs.github.io

 

이번에는 Listener rules의 순서를 직접 설정해 보겠습니다.


alb.ingress.kubernetes.io/group.order: 
어노테이션을 각각 0, 1로 설정해서 추가했습니다.

테스트의 간소화를 위해 하위경로는 삭제하고 새로 적용했습니다.

red의 우선순위가 정의한 대로 blue보다 앞선 것을 확인할 수 있습니다.

target groups 리소스의 이름은
k8s-<namespace>-<서비스명에서-를 지우고 남은 8글자>-<난수>로 생성됩니다.

k8s-default-servicer-6e532b6e09 는 service-red
그 아래 serviceb는 service-blue입니다.

타겟그룹바인딩은 eks에서도 아래 명령어로 확인 가능합니다.

k get targetgroupbinding
NAME                              SERVICE-NAME   SERVICE-PORT   TARGET-TYPE   AGE
k8s-default-serviceb-68dfb02b36   service-blue   80             ip            22h
k8s-default-servicer-6e532b6e09   service-red    80             ip            22h

 

 

마지막으로 load-balancer-name을 설정해보겠습니다.

어노테이션을 추가하고 hodong이라는 이름을 지정했습니다.
load-balancer-name의 값은 32 글자를 넘으면 에러를 일으킬 수 있다고 합니다. 너무 길지 않게 원하는 이름을 써줍니다.

수정하고 apply 합니다.

k apply -f red.yaml
deployment.apps/deployment-red unchanged
service/service-red unchanged
ingress.networking.k8s.io/ingress-red configured

 

이름만 추가해서 수정한다고 로드밸런서가 새로 생성되지는 않네요.

name과 ingressGroup의 배타적인 관계 때문인것 같습니다. (확실하지 않음)

load-balancer-name과 group.name의 유무, load-balancer-name이 같을 때, 다를 때 여러 조건에서
ingress resource 수정할 때 결과를 테스트해보았지만 간단하게 설명할 만한 결과를 얻지 못했습니다.

간결하게 정리하면 load-balancer-name과 group.name은 처음에 정의할 때 잘 정의해서 쓰시길 바랍니다.

실제 운영 상황이 아닌, 학습 용도라면 ingress resource를 지우고, aws 콘솔에서 로드밸런서가 삭제 되었는지 확인한 후
다시 생성해서 (configure가 아닌) create 되는 상황으로 사용하시는게 좋을 듯합니다.

 

마지막으로 인그레스 리소스를 모두 삭제하고 생성 된 로드밸런서가 없는 상태에서
group.name과 load-balancer-name을 모두 입력하고 적용해보겠습니다.

 

Load balancer의 Name과 DNS name에는 color보다 test가 우선해서 적용되는것을 확인할 수 있습니다.

로드밸런서의 tags에서 ingress.k8s.aws/stack의 값이 color 인것도 확인 가능합니다. 

 

 

728x90