AWS EKS 에서 Istio 와 Application Load Balancer 연결

Thomas Kim·2021년 12월 17일
2

EKS 에서 Istio 를 설치하면 기본적으로 Classic Load Balancer (CLB) 를 사용하여 설치가 된다. 공식적으로 CLB가 discontinued 된다는 notice는 없지만 CLB는 권장되지 않는다. 결국 L4 Network Load Balancer(NLB) 또는 L7 Application Load Balancer(ALB)로 변경해야 한다. 하지만 AWS WAF 와 같은 서비스를 사용하기 위해서는 반드시 ALB를 사용해야 한다. 여기서는 Istio 와 ALB를 연결해 본다. (NLB를 사용하는 방법은 많이 나와있지만 ALB를 사용하는 방법은 찾기 힘들다...)
https://rtfm.co.ua/en/istio-external-aws-application-loadbalancer-and-istio-ingress-gateway/ 를 참고하였다.

변경되는 Architecture

전체적인 architecture는 이렇게 변경된다. 기존 istio ingress gateway의 service type 은 LoadBalancer 에서 NodePort로 변경하여 기존 CLB가 삭제되고, 대신 Kubernetes 의 Ingress resource를 통해 ALB를 생성한다. 그리고 ALB에서 TLS termination 을 하고 모든 request를 istio ingress gateway pod로 보내고 istio ingress gateway가 application service로 routing 을 하게 된다.


ACM 을 통한 TLS 인증서 설치

첫째, TLS 인증서를 AWS ACM 에 import 한다.
https://docs.aws.amazon.com/acm/latest/userguide/import-certificate-api-cli.html


AWS Load Balancer Controller 설치

ALB를 사용하기 위해서는 AWS Load Balancer Controller가 필요하다. Bastion 서버에서 아래 순서대로 설치를 진행한다.
https://docs.aws.amazon.com/eks/latest/userguide/aws-load-balancer-controller.html

IAM Policy 생성

AWS Load Balancer Controller를 위한 IAM Policy를 다운로드한다.

curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/install/iam_policy.json

IAM policy를 생성한다.

$ aws iam create-policy \
    --policy-name AWSLoadBalancerControllerIAMPolicy \
    --policy-document file://iam_policy.json

IAM Role 및 Kubernetes의 Service Account 생성

위에서 생성된 IAM Policy를 이용하여 아래와 같이 생성한다. 여기서 attach-policy-arn 을 위에서 생성한 policy를 넣는다.

eksctl create iamserviceaccount \
  --cluster=eks-demo \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --role-name AmazonEKSLoadBalancerControllerRole \
  --attach-policy-arn=arn:aws:iam::931639357206:policy/AWSLoadBalancerControllerIAMPolicy \
  --approve

Helm 설치 및 repository 추가

AWS Load Balancer Controller를 Helm을 통해 설치하기 때문에 Helm도 설치하고 eks-charts repository도 추가한다.

$ sudo snap install helm --classic
$ helm repo add eks https://aws.github.io/eks-charts
$ helm repo update eks

AWS Load Balancer Controller 설치

이제 AWS Load Balancer Controller 를 설치한다.

$ helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=eks-demo \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller \

controller 가 제대로 설치되었는지 확인한다.

kubectl get deployment -n kube-system aws-load-balancer-controller

Istio 설정 변경

이제 Istio 의 ingress gateway의 service type을 NodePort로 변경하고 ALB가 istio ingreas gateway로 health check 을 할 수 있도록 관련 정보를 넣어준다.

Health check 을 위한 Port number 확인

우선 ALB 가 health check을 위해 사용할 istio ingress gateway 의 health check 관련 nodePort number를 알아본다.

$ kubectl get service istio-ingressgateway -n istio-system -o jsonpath='{.spec.ports[?(@.name=="status-port")].nodePort}'

얻어진 Port number를 아래에서 사용한다.

Istio 설정 업데이트

AWS EKS에 Istio 설치 및 설정 에서 사용한 istio-operator.yaml 를 아래와 같이 업데이트 한다. (Service type 과 service annotation 을 추가한다.)

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  namespace: istio-system
  name: istiocontrolplane
spec:
  profile: default
  components:
    egressGateways:
    - name: istio-egressgateway
      enabled: true
      k8s:
        hpaSpec:
          minReplicas: 2
    ingressGateways:
    - name: istio-ingressgateway
      enabled: true
      k8s:
        hpaSpec:
          minReplicas: 2
        service:
          type: NodePort # ingress gateway 의 NodePort 사용
        serviceAnnotations:  # Health check 관련 정보
          alb.ingress.kubernetes.io/healthcheck-path: /healthz/ready
          alb.ingress.kubernetes.io/healthcheck-port: "32197" # 위에서 얻은 port number를 사용
    pilot:
      enabled: true
      k8s:
        hpaSpec:
          minReplicas: 2
  meshConfig:
    enableTracing: true
    defaultConfig:
      holdApplicationUntilProxyStarts: true
    accessLogFile: /dev/stdout
    outboundTrafficPolicy:
      mode: REGISTRY_ONLY
  • Istio ingress gateway 의 service type을 NodePort로 설정한다.
  • 전 단계에서 얻은 port number를 healthcheck-port 에 넣어 health check 관련 정보를 istio ingress gateway 에 annotation 으로 저장한다.

업데이트된 정보를 Istio 에 적용한다.

$ istioctl install -f istio-operator.yaml

여기까지 하면 기존 ingress gateway의 service type을 기존 LoadBalancer 에서 NodePort로 변경하였기 때문에 CLB (Classic Load Balancer)는 삭제된다.


ALB 생성

이제 마지막으로 Kubernetes 의 Ingress를 통해 ALB를 생성한다. (AWS Load Balancer Controller는 Kubernetes의 Ingress 를 통해 ALB 를 생성한다)
아래와 같이 kube-ingress.yaml 파일을 생성한다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-alb
  namespace: istio-system
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:ap-northeast-2:9316393572~~~"
    alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
spec:
  rules:
  - http:
      paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: ssl-redirect
              port:
                name: use-annotation
        - path: /
          pathType: Prefix
          backend:
            service:
              name: istio-ingressgateway
              port:
                number: 80
  • certificate-arn 에는 AWS ACM 에 생성한 TLS certificate의 ARN을 입력한다.

아래와 같이 Ingress를 생성하여 ALB 생성을 완료한다.

$ kubectl apply -f kube-ingress.yaml

이렇게 기존 CLB를 삭제하고 ALB 로 대체하면서 TLS Termination 은 ALB 에서 일어나고 ALB는 istio-system namespace 에 배포되어 있는 istio-ingressgateway 로 request를 보내게 되고 istio-ingressgateway는 비로서 서비스로 라우팅을 하게 된다.


여기까지 하면 EKS 에 상용에서 사용가능한 Kubernetes Cluster 생성 및 ALB를 통한 TLS Termination, istio ingress gateway의 라우팅이 가능해 진다. 결국 AWS의 WAF 와 같이 ALB가 필수인 서비스를 사용할 수 있다.

profile
Software Developer at SK Telecom

0개의 댓글