2023. 5. 1. 23:09ㆍDev/EKS
이 글은 AWS EKS에서 NGINX-Ingress Controller를 설치하고
nginx.ingress.kubernetes.io/rewrite-target annotations를 사용해 여러 애플리케이션을 여러 경로로 라우팅 하는 예제입니다.
해결하려는 문제
EKS에서 ALB와 ingress로만 Path-based routing을 하면 경로 영향을 받습니다. (ALB ingress는 rewrite를 지원하지 않습니다)
아래 Ingress는 example.com/two 로 온 요청을 service-two로 보냅니다. (example.com/two -> service-two의 /two )
하위 경로를 내부 서비스의 root로 보내려면 (example.com/two -> service-two의 / )
nginx ingress annotation 중 rewrite-target을 사용합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-example
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-one
port:
number: 80
- path: "/two"
pathType: Prefix
backend:
service:
name: service-two
port:
number: 80
사전 준비
EKS v1.25 클러스터와 AWS 로드밸런서 컨트롤러 v2.5가 있다고 가정하고 진행합니다.
AWS EKS cluster 프로비저닝과 Aws-load balancer-controller 설치는 아래 포스트와 다른 문서들을 참고하세요.
(아래 포스트는 EKS v1.24와 controller v2.4.7을 설치합니다.)
https://nauco.tistory.com/89
https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/getting-started-eksctl.html
https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.5/deploy/installation/
사전 준비 중 생길 수 있는 오류들
1.
AWS에서 소개하는 AWS Load Balancer Controller 설치 가이드는 최신버전이 아닐 수 있으니
위에서 링크한 https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.5/ 공식문서에서 확인하세요.
(구글에서 검색해서 들어가면 이전 버전으로 링크될 때가 많습니다)
2.
로드밸런서 컨트롤러 설치 중 IAM 정책 생성 중에 아래와 같은 에러가 발생한다면
An error occurred (EntityAlreadyExists) when calling the CreatePolicy operation: A policy called AWSLoadBalancerControllerIAMPolicy already exists. Duplicate names are not allowed.
-> iam policy에서 해당 이름의 policy를 지우고 새로 만들거나 aws iam update-policy 사용해서 최신 정책으로 업데이트합니다.
3. aws-load balancer-controller 설치 전에
serviceaccount가 잘 만들어지지 않는다면 기존에 같은 이름의 클러스터를 생성하다 실패한 것이 원인일 수 있습니다.
aws console에서 cloudformation에서 위와 비슷한 이름의 iamserviceaccount 스택을 지우고 다시 시도합니다.
Nginx-ingress Controller 설치
Nginx ingress controller YAML로 설치하는 방법과
Nginx ingress controller Helm 으로 설치하는 방법이 있습니다.
아래 명령어를 사용해서 헬름으로 ingress-nginx를 설치합니다.
helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx --create-namespace
성공하면 아래와 같이 ingress리소스에서 ingressClassName을 nginx 세팅하고 사용하는 예제를 보여줍니다.
helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx --create-namespace
Release "ingress-nginx" does not exist. Installing it now.
NAME: ingress-nginx
LAST DEPLOYED: Sat Apr 29 17:59:59 2023
NAMESPACE: ingress-nginx
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The ingress-nginx controller has been installed.
It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status by running 'kubectl --namespace ingress-nginx get services -o wide -w ingress-nginx-controller'
An example Ingress that makes use of the controller:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example
namespace: foo
spec:
ingressClassName: nginx
rules:
- host: www.example.com
http:
paths:
- pathType: Prefix
backend:
service:
name: exampleService
port:
number: 80
path: /
# This section is only required if TLS is to be enabled for the Ingress
tls:
- hosts:
- www.example.com
secretName: example-tls
If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided:
apiVersion: v1
kind: Secret
metadata:
name: example-tls
namespace: foo
data:
tls.crt: <base64 encoded cert>
tls.key: <base64 encoded key>
type: kubernetes.io/tls
헬름 성공 메시지에서 알려주는대로
kubectl --namespace ingress-nginx get services -o wide -w ingress-nginx-controller
명령어를 입력하고 잘 떴는지 확인합니다.
저는 클러스터에 특별히 설치된 리소스들이 없어서
kubectl get svc -A
명령어로 확인했습니다.
이름이 ingress-nginx-controller 이고 TYPE이 LoadBalancer인 서비스를 확인 가능합니다.
주소가 k8s- 로 시작하는 NLB가 생성 된 것을 확인할 수 있습니다.
만들어진 로드밸런서의 주소가 a로 시작한다면 클래식 로드밸런서(CLB)가 생성된 것입니다.
(service/ingress-nginx-controller의 EXTERNAL-IP 확인)
AWS LoadBalancer Controller를 설치 안했거나, v2.5보다 낮은 버전인지 확인해보세요.
k get all -n ingress-nginx
NAME READY STATUS RESTARTS AGE
pod/ingress-nginx-controller-6b8bfd7f69-gk469 1/1 Running 0 7m15s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-nginx-controller LoadBalancer 10.100.208.234 a70eaf767a3c54dbaa1d6069010724c4-1121914811.ap-northeast-2.elb.amazonaws.com 80:30653/TCP,443:31686/TCP 7m15s
service/ingress-nginx-controller-admission ClusterIP 10.100.121.211 <none> 443/TCP 7m15s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-nginx-controller 1/1 1 1 7m15s
NAME DESIRED CURRENT READY AGE
replicaset.apps/ingress-nginx-controller-6b8bfd7f69 1 1 1 7m15s
ingress-nginx-controller가 사용하는 Network Loadbalancer를 Internet-facing으로 재 설치
default로 만들어진 NLB는 Internal입니다.
NLB를 테스트하기 편하도록 외부로 노출해서 다시 만들겠습니다.
helm uninstall ingress-nginx -n ingress-nginx
명령어를 실행하고 나오는
release "ingress-nginx" uninstalled
위 결과는 helm으로 설치한 ingress-nginx를 삭제한 것이지, 로드밸런서의 삭제를 의미하지 않습니다.
aws console에서 로드밸런서 삭제된 것 확인하고 아래 옵션을 추가해서 다시 설치합니다.
helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--set controller.service.annotations."service\.beta\.kubernetes\.io\/aws-load-balancer-scheme"=internet-facing \
--namespace ingress-nginx --create-namespace
(사실 아래 명령어로 될 줄 알았는데 안되네요...)
helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--set controller.service.external.enabled=true \
--namespace ingress-nginx --create-namespace
로드밸런서가 프로비저닝 된 후 (약 3분 소요)
콘솔에서 확인 가능한 LoadBalancer의 DNS name (또는 svc의 EXTERNAL-IP)으로 접근했을 때, 404 Not Found가 나오면 성공
샘플 웹 애플리케이션 배포해서 Ingress-nginx 테스트
위 소스를 사용해서 테스트합니다.
1. nginx ingress example
namespace를 만들고 app-one과 ingress-one을 apply합니다.
kubectl create ns app
kubectl apply -f app-one.yaml
kubectl apply -f ingress-one.yaml
로드밸런서의 주소로 접근하면 첫 번째 앱으로 연결됩니다.
2. nginx ingress rewrite example
ingress-one을 지우고 rewrite annotation이 적용 된 ingress-two를 적용합니다.
kubectl delete -f ingress-one.yaml
kubectl apply -f ingress-two.yaml
루트경로는 연결된 서비스가 없으니 404페이지가 뜹니다.
/red로 접근하면 service-one의 루트경로 ( / )가 호출됩니다.
/red/abc는 service-one에서 (/abc)로 연결됩니다.
3. nginx ingress rewrite-target routing
ingress-two를 지우고
app-two와 ingress-app을 apply합니다.
kubectl apply -f app-two.yaml
kubectl delete -f ingress-two.yaml
kubectl apply -f ingress-app.yaml
아래와 같은 결과를 확인합니다.
ALB path-based routing과 (no rewrite)
nginx-ingress rewrite를 써서 라우팅한것을 비교해봅니다.
eks nlb ingressNginx (위) vs eks alb ingress (아래)
https://kubernetes.github.io/ingress-nginx/
정리
k get svc -A
명령어로 로드밸런서를 확인하고
k delete svc <service-name> -n <namespace>
명령어로 로드밸런서를 만든 서비스를 지워줍니다.
(혹은 aws 콘솔에서 로드밸런서를 직접 지웁니다.)
eksctl delete cluster --name <cluster-name>
명령어로 클러스터를 삭제합니다.
LB삭제 안하고 eksctl delete 하면 로드밸런서 안지워집니다.
클러스터만 지워지고 LoadBalancer 남아있으면 aws 콘솔가서 지우고
클라우드포메이션까지 확인해서 테스트에 사용한 aws 리소스들 지워줍니다.
후기
AWS에서? ALB에서? AWS Load Balancer Controller(LBC)에서?
왜 심플한 rewrite path를 지원하지 않는지 모르겠습니다.
도메인과 서브도메인 문제는 인그레스에서 라우팅하면 당연히 겪을 문제일텐데요.
물론 애플리케이션에서 처리할 수도 있고, 이 글에서 처럼 nginx-ingress로 해결할 수 있지만
2019년에 작성된 issue에 아직도 코멘트가 달리는것만 봐도 저만 가진 생각은 아닌것 같습니다.
https://github.com/kubernetes-sigs/aws-load-balancer-controller/issues/835
'Dev > EKS' 카테고리의 다른 글
AWS EKS event, could not create volume in EC2 (0) | 2023.06.02 |
---|---|
eksctl version upgrade For MacOS (0) | 2023.06.02 |
AWS EKS에 ALB를 이용해 여러 서비스 연결하기 (0) | 2023.04.22 |
EKS에 CLB, NLB, ALB 만들기, AWS Load Balancer Controller 사용 (1) | 2023.04.09 |
eksctl pods are unevictable from node 에러 해결하기 (0) | 2023.02.28 |