Cloud

Amazon EKS Tutorial - Part.4

Operation CWAL 2021. 3. 17. 22:22

Application 배포

새로운 클러스터 생성

본격적으로 EKS 클러스터에 App을 배포하는 과정에 대해 알아보자. 실습 환경 구성을 위해 기존 클러스터는 제거하고 아래 명령어로 새로운 클러스터를 생성한다. 이번엔 yaml 파일을 사용하는 대신 Imperative 방식으로 진행하였다.

eksctl create cluster \
    --name eks-from-eksctl \
    --version 1.19 \
    --region ap-northeast-2 \
    --nodegroup-name workers \
    --node-type t3.medium \
    --nodes 2 \
    --nodes-min 1 \
    --nodes-max 4 \
    --ssh-access \
    --ssh-public-key eks-access \
    --managed

ClusterConfig 파일을 작성해봤다면, 위 옵션을 이해하는 것은 그리 어렵지 않을 것이다. K8s v1.19를 사용하는 클러스터를 ap-northeast-2(Seoul) region에 생성한다. 기본 2개, 최소 1개, 최대 4개의 on-damand node를 갖는 nodegroup 'workers'를 배치한다. '--managed' 옵션은 생소할 수 있는데, 말그대로 EKS에서 관리(provision, register, etc)해주는 nodegroup을 의미한다. 자세한 내용은 링크를 참고하길 바란다. 참고로 기존 Declarative 방식과 동일하게 완료까지 15~20분 정도 소요된다.

 

 

Gusetbook App

이번에 배포할 Gusetbook은 매우 단순한 구조의 Webapp으로 K8s 예제로 자주 사용하는 Application이다. Frontend에는 PHP로 만들어진 Guestbook이 위치하고, Backing Service로 Redis가 Master 1개, Slave 2개로 구성된다. Redis에 쓰기 작업은 Master에서만 가능하며, 읽기 작업은 Slave에 요청한다. 중요한 점은 Guestbook 서비스를 외부에 제공하기 위해 Loadbalancer 타입의 Service를 정의한다는 것이다. 이 경우 AWS에서 Classic Loadbalanacer(L7)가 자동으로 생성되며, Guestbook Frontend 서비스와 연결된다.

 

Guestbook App on AWS

 

Redis Master 배포

kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-master-controller.json

kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-master-service.json

Redis Slave 배포

kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-slave-controller.json

kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-slave-service.json

Frontend App 배포

kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/guestbook-controller.json

kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/guestbook-service.json

참고로 ReplicationController는 Deprecated된 리소스이므로, 실제 환경에선 ReplicaSet 또는 Deployment를 사용해야 한다.

 

아래와 같이 K8s 리소스가 모두 정상적으로 생성되었는지 체크한다.

service/guestbook의 내용을 보면 EXTERNAL-IP가 존재하는데, 다름아닌 ELB에 할당된 URL로 해당 주소를 통해 Internet에서 접근이 가능하다. 해당 URL을 브라우저에 붙여넣기하고 포트번호 3000번을 추가하여, 다음과 같은 화면이 나오면 성공이다.

내친김에 메시지도 입력해보자. Redis에 데이터를 저장하기 때문에, 이전에 입력한 메시지가 화면에 출력되며, 방명록 기능을 제공한다.

 

Ingress 적용

Application을 외부에 공개해야 할 때마다, 매번 Loadbalancer를 추가하기엔 비용적인 문제가 발생한다. 또한 Classic Loadbalancer는 HTTP Path에 따른 Routing을 지원하지 않기 때문에 Production Level에서 많은 서비스를 제공하기엔 다소 부적합하다.

이러한 문제를 해결하기 위해 가장 먼저 Ingress Controller를 서비스 앞에 배치하고, Ingress를 추가하여 개별 서비스를 HTTP Path로 접근하는 방법이 있다.

 

기존 클러스터에 Ingress Controller를 추가한다. 다양한 솔루션(ex: ALB, HAProxy)이 있지만, 비교적 쉽게 사용할 수 있는 Nginx Ingress Controller를 사용하고자 한다. Helm 차트 형식으로 Manifest 파일을 제공하므로, 우선 아래와 같이 helm을 설치한다.

$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
$ chmod 700 get_helm.sh
$ ./get_helm.sh

다음은 helm 차트 'nginx-ingress-controller'를 배포한다.

$ kubectl create namespace nginx-ingress-controller

$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
$ helm repo add stable https://charts.helm.sh/stable
$ helm repo update

$ helm install nginx-ingress-controller ingress-nginx/ingress-nginx

'nginx-ingress-controller' namespace에 리소스가 제대로 생성되었는지 체크한다.

 

이제 Nginx Ingress Controller 구성을 위한 Deployment와 Service가 모두 생성된 상태이다. 특히, 'nginx-ingress-controller-ingress-nginx-controller' Service의 경우, EXTERNAL-IP로 ELB가 할당된 것으로 조회되며, 이를 AWS 콘솔에서 이를 확인해보면, Classic Loadbalancer임을 알 수 있다.

물론, 해당 LB는 Nginx Pod으로 트래픽을 전달하는 역할일 뿐, 실제 Path에 따른 Service Routing은 Nginx에서 처리한다. 이제 아래와 같은 Ingress Rule을 추가해보자.

apiVersion: extensions/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
  name: guestbook
  namespace: default
spec:
  rules:
    - http:
        paths:
          - backend:
              service:
                name: guestbook
                port:
                  number: 3000
            path: /
            pathType: Prefix

비교적 간단한 rule이며, Path가 '/'인 경우, guestbook Service의 3000번 포트로 forwarding된다. 확인을 위해, nginx-ingress-controller의 DNS Name으로 접속해보자. 이제는 HTTP Path에 따라 서비스가 결정되므로 포트 번호는 따로 입력할 필요가 없다.

 

guestbook App에 할당한 LoadBalancer 타입의 Service는 더 이상 필요하지 않으므로, ClusterIP 타입의 Service로 변경하자. 기존 Service는 삭제하고 새로 생성해야 한다. 이 과정에서 해당 Service에 할당한 ELB는 삭제된다.

$ kubectl delete service guestbook

 

 

아래와 같은 Manifest 파일 'guestbook-service.yaml'을 추가하고, 새로 적용한다.

apiVersion: v1
kind: Service
metadata:
  annotations:
  labels:
    app: guestbook
  name: guestbook
  namespace: default
spec:
  ports:
  - port: 3000
    protocol: TCP
    targetPort: http-server
  selector:
    app: guestbook
$ kubectl apply -f guestbook-service.yaml

브라우저에서 다시 접속해보자. Service 타입을 수정했지만, 기존과 동일하게 접근할 수 있다.

이런 방식으로 개별 서비스에 대해 Ingress Rule을 추가하여 HTTP Path 기반의 Routing이 가능하며, 하나의 ELB를 사용하여 여러개의 서비스를 접근할 수 있으므로 매우 효율적이다.

'Cloud' 카테고리의 다른 글

Amazon EKS Tutorial - Part.6  (0) 2021.03.22
Amazon EKS Tutorial - Part.5  (0) 2021.03.20
Amazon EKS Tutorial - Part.3  (0) 2021.03.16
Amazon EKS Tutorial - Part.2  (1) 2021.03.15
Amazon EKS Tutorial - Part.1  (0) 2021.03.13