쿠버네티스의 NodePort 기본 범위는 30000-32767 이고, 이 값은 kube-apiserver 의 --service-node-port-range 플래그로 정한다. 관리형 컨트롤 플레인인 EKS 는 apiserver 의 실행 인자를 사용자가 건드릴 수 없으므로 이 범위를 바꿀 방법이 없다. 직접 구축한 클러스터라면 매니페스트를 고쳐 바꿀 수 있지만 EKS 에서는 대안을 찾는 편이 빠르다.
"80 번이나 443 번으로 노드에 직접 붙고 싶다" 는 요구라면 선택지는 셋이다.
| 방법 | 성격 |
|---|---|
type: LoadBalancer 서비스 |
NLB 또는 ALB 가 앞에 붙는다. 로드밸런서 쪽 포트는 자유롭게 정할 수 있고, 뒤쪽 NodePort 는 여전히 3만번대지만 밖에서는 보이지 않는다 |
| Ingress 컨트롤러 | 하나의 로드밸런서 뒤에서 호스트·경로로 나눈다. 서비스마다 로드밸런서를 만들지 않아도 된다 |
hostPort |
파드가 뜬 노드의 해당 포트를 그대로 점유한다. 포트를 직접 지정할 수 있지만 노드당 하나만 뜰 수 있고, 노드가 죽으면 그 주소는 사라진다 |
일반적으로는 LoadBalancer 서비스나 Ingress 를 쓴다. hostPort 는 노드를 고정해도 되는 에이전트성 워크로드에 한정한다.
type: LoadBalancer 로 만들었는데 EXTERNAL-IP 가 계속 <pending> 이면 AWS 쪽에서 로드밸런서가 만들어지지 않은 것이다. 이벤트에 이유가 남는다.
kubectl describe svc <SERVICE> -n <NAMESPACE> | sed -n '/Events/,$p'
확인 순서는 다음과 같다.
인트리 컨트롤러가 만드는 클래식 로드밸런서가 아니라 NLB · ALB 를 쓰려면 AWS Load Balancer Controller 가 필요하다.
kubectl get deploy -n kube-system aws-load-balancer-controller
kubectl logs -n kube-system deploy/aws-load-balancer-controller --tail=50
컨트롤러는 태그를 보고 로드밸런서를 놓을 서브넷을 고른다. 태그가 없으면 "서브넷을 찾지 못했다" 는 이벤트가 남고 Pending 에서 멈춘다.
aws ec2 describe-subnets --filters "Name=vpc-id,Values=<VPC_ID>" \
--query 'Subnets[].{Id:SubnetId,Az:AvailabilityZone,Tags:Tags}'
| 용도 | 태그 |
|---|---|
| 인터넷에 열리는 로드밸런서용 퍼블릭 서브넷 | kubernetes.io/role/elb = 1 |
| 내부용 로드밸런서용 프라이빗 서브넷 | kubernetes.io/role/internal-elb = 1 |
최소 두 개의 가용 영역에 태그가 붙어 있어야 한다. 한 영역만 태그돼 있으면 만들어지지 않는다.
컨트롤러의 서비스 어카운트에 IRSA 로 역할이 연결돼 있어야 한다.
kubectl describe sa aws-load-balancer-controller -n kube-system | grep eks.amazonaws.com/role-arn
aws ec2 describe-subnets --subnet-ids <SUBNET_ID> \
--query 'Subnets[].AvailableIpAddressCount'
NLB 로 만들 때 서비스에 붙이는 어노테이션이다. 컨트롤러 버전에 따라 이름이 달라진 적이 있으므로, 쓰고 있는 컨트롤러 버전의 문서에서 확인한다.
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
spec:
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: http
- name: https
port: 443
targetPort: https