1. 개요
현업에서 외부 트래픽 인입을 받아내기 위해 Istio를 사용중인데, default 설정을 사용하면 CLB가 설치된다.
EKS로 쿠버네티스를 운영중인 환경에서 Istio로 ALB, NLB를 각 환경에 맞게 사용하고 싶을 경우에 어떻게 해야 할까?
## 전제 조건 ##
- AWS Load Balancer Controller 설치
AWS Load Balancer Controller는 Kubernetes에서 YAML 파일을 배포하는 것 만으로 AWS Load Balancer Controller 파드가 이를 감지하여 AWS API를 사용하여 요청한 대로 Load Balancer를 설치 및 구성해주는 오픈소스이다.
해당 AWS Load Balancer Controller가 설치되어 있지 않다면 내장 설치된 Controller를 통해 LB를 설치해야 하는데 지원되는 부분도 많지 않고 ALB를 설치할 수 없다. 따라서 필수적으로 설치해주어야 한다.
2. 설정 방법
1. AWS Load Balancer Controller가 설치되어 있는지 확인
- 설치되어 있지 않다면 따로 설치해주어야 한다.

2. Istio 설치 준비
- Istio는 오픈소스이기 때문에 버전에 따라 굉장히 민감하게 동작될 수 있으므로 버전을 고정하여 구성하는 것을 권장한다.
- 필자가 설치할 버전은 1.12.1이다.
- Helm Charts 또한 버전을 동일하게 가져가기 위해 1.12.1을 지정해준다.
- istioctl 명령어 또한 버전을 동일하게 가져가기 위해 1.12.1 버전의 CLI를 다운로드 받아준다.
(istioctl 명령어는 용량이 많이 나가기 때문에 .gitignore에 추가해줘야 한다.)
./bin/istioctl version
client version: 1.12.1
control plane version: 1.12.1
data plane version: 1.12.1 (7 proxies)
3. Operator로 Istio 설치
bin : istioctl이 들어있는 폴더
ingress : ALB를 구성하기 위한 Ingress yaml 파일 폴더
manifests : Helm charts가 구성되어 있는 폴더

istio-operator.yaml
여기서 중요한 부분은 다음과 같다.
[1] label -> istio: ingressgateway / istio: ingressgateway-alb / istio: ingressgateway-ext-alb
Istio를 설치하고 가장 중요한 Traffic 인입을 정의할 때 Istio Gateway, Virtual Service에서 어떤 Istio pod로 인입되는 트래픽에 대해 트래픽을 처리할 것인지 설정하게 된다.
무슨 말인지 잘 이해가 안 될 수 있어 살짝 풀어서 정리해봄
AWS LB (ALB는 Ingress(규칙 명세서)에 의해 생성됨) -> Istio Service -> Istio Pod
여기서 Isito Pod의 Label에 따라서 어떤 Istio Gateway에 정의된 Rule / Setting 값을 따를 것인지 정하게 된다.
[참고용 : Istio Gateway 설정]

추후 Istio Gateway를 설정할 때 istio Label 설정하는 부분에 위의 istio 레이블을 각각 고려하여 선택해주면 된다.
[2] ALB를 위한 Istio pod & service를 구성하는 부분인데 사용되지 않는 NodePort를 하나 선택한 뒤 status-port와 healthcheck-port를 같은 값으로 지정해주면 된다.

[3] NLB를 생성하는 Annotation에서 aws-load-balancer-type을 "external"로 지정해주어야 내장 LB Controller가 이를 감지하는게 아니라 외부 Controller, 즉 AWS Load Balancer Controller가 이를 감지하여 NLB를 생성하게 된다.
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
namespace: istio-system
name: istiocontrolplane
spec:
profile: default
components:
egressGateways:
- name: istio-egressgateway
enabled: false
ingressGateways:
# NLB
- name: istio-ingressgateway
enabled: true
label:
istio: ingressgateway
k8s:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 2000m
memory: 1024Mi
hpaSpec:
minReplicas: 1
service:
externalTrafficPolicy: Cluster
type: LoadBalancer
ports:
# Status Port
- port: 15021
targetPort: 15021
name: status-port
protocol: TCP
# HTTP Port
- port: 80
targetPort: 8080
name: http2
protocol: TCP
# HTTPS Port
- port: 443
targetPort: 8443
name: https
protocol: TCP
serviceAnnotations: # NLB
service.beta.kubernetes.io/aws-load-balancer-name: istio-ingress-nlb
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-internal: "true"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/load-balancer-source-ranges: "XXXXXXX, XXXXXXXXX"
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"
service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy: ELBSecurityPolicy-2016-08
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: XXXXXXXXXXXXXXXXXXXXXXXXXXXX
service.beta.kubernetes.io/aws-load-balancer-healthcheck-path: /healthz/ready
service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "15021"
service.beta.kubernetes.io/aws-load-balancer-attributes: load_balancing.cross_zone.enabled=true
# ALB
- name: istio-ingressgateway-alb
enabled: true
label:
istio: ingressgateway-alb
k8s:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 2000m
memory: 1024Mi
hpaSpec:
minReplicas: 1
maxReplicas: 2
serviceAnnotations: # Health check 관련 정보
alb.ingress.kubernetes.io/healthcheck-path: /healthz/ready
alb.ingress.kubernetes.io/healthcheck-port: "30621" # Status Port에서 지정한 nodePort 지정
service:
type: NodePort # ingress gateway 의 NodePort 사용
ports:
- name: status-port
protocol: TCP
port: 15021
targetPort: 15021
nodePort: 30621
- name: http2
protocol: TCP
port: 80
targetPort: 8080
- name: https
protocol: TCP
port: 443
targetPort: 8443
# ALB
- name: istio-ingressgateway-ext-alb
enabled: true
label:
istio: ingressgateway-ext-alb
k8s:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 2000m
memory: 1024Mi
hpaSpec:
minReplicas: 1
maxReplicas: 2
serviceAnnotations: # Health check 관련 정보
alb.ingress.kubernetes.io/healthcheck-path: /healthz/ready
alb.ingress.kubernetes.io/healthcheck-port: "30622" # Status Port에서 지정한 nodePort 지정
service:
type: NodePort # ingress gateway 의 NodePort 사용
ports:
- name: status-port
protocol: TCP
port: 15021
targetPort: 15021
nodePort: 30622
- name: http2
protocol: TCP
port: 80
targetPort: 8080
- name: https
protocol: TCP
port: 443
targetPort: 8443
이후에 다음의 명령어로 설치를 수행하면 된다. dry-run 또한 옵션으로 가능하다.
./bin/istioctl install --manifests ./manifests -f istio-operator.yaml
4. Ingress로 ALB 설치
이제 Ingress 리소스를 배포하여 ALB를 생성해주면 된다.

주의할 점으로 service의 name에 위에 Operator로 생성한 Istio Service의 이름과 Port를 정확히 매핑해주어야 한다.
그래야 해당 ALB로 인입되는 트래픽이 ALB를 위해 생성된 Istio Pod로 트래픽이 라우팅이 될 것이다.

ALB는 Ingress 까지 생성해야 배포가 되고, NLB는 Istio Operator를 배포하면 생성이 된다.

NLB는 타겟 타입을 IP로 했기 때문에 정확히 Istio Pod의 IP로만 NLB 타겟 그룹의 트래픽이 라우팅된다. (AWS VPC CNI이기 때문)
ALB는 NodePort로 설정했기 때문에 모든 Node의 nodePort로 트래픽이 라우팅되어, 라우팅 된 이후 iptables에 의해 내부적으로 실제 Istio Pod로 라우팅이 된다.
[NLB]

[ALB]

'AWS' 카테고리의 다른 글
[EKS] CA의 대체, Karpenter 사용 후기 (2) | 2023.04.15 |
---|---|
[EKS] CoreDNS 운영 시 소소한 팁 (Rcode, ndots) (0) | 2022.11.11 |
[EKS 애드온 #2] Cluster Autoscaler Helm으로 설치하기 (0) | 2022.08.27 |
[EKS 애드온 #1] External DNS Helm으로 설치하기 (0) | 2022.08.27 |
[EKS] EKS Cluster 구축 시 고려 사항 정리 (Terraform, Terragrunt, IRSA, Atlantis, Addon, ..) (1) | 2022.08.12 |