EKS 클러스터에 간단한 Flask 어플리케이션 배포하기

2019-12-08

서버 로그 수집에 Fluent Bit 를 도입할 수 있을지 탐색할 계획입니다. 현재 소속된 팀의 서버 개발자 분들은 Amazon EKS 로 Kubernetes 클러스터를 운영하고 있습니다. 그래서 일단 Kubernetes 에 대해 어느정도 이해가 필요할 것 같아서 직접 써보며 익혀보려고 합니다.

EKS 클러스터 생성

Getting Started with eksctl 문서를 참고하여 Homebrew 로 eksctl 을 설치합니다. 그러면 kubectl 과 aws-iam-authenticator 도 설치된다고 합니다. AWS CLI 는 예전에 설치했었습니다.

brew tap weaveworks/tap
brew install weaveworks/tap/eksctl

eksctl 명령어로 EKS 클러스터와 Managed Node Group 을 생성합니다. 마침 re:invent 때 Amazon EKS on AWS Fargate 가 GA 로 발표 되었기에 관심이 갔는데, 아직 서울 리전은 지원하지 않습니다. 그러니 Cluster with Linux-only workloads 탭의 명령어를 적당히 바꿔서 사용합니다.

eksctl create cluster \
--name kubernetes-study \
--version 1.14 \
--region ap-northeast-2 \
--nodegroup-name flask \
--node-type t3.medium \
--nodes 2 \
--nodes-min 2 \
--nodes-max 2 \
--managed

Flask 어플리케이션 준비

A Minimal Application 문서를 참고하여 정말 간단한 어플리케이션을 app.py 로 준비합니다.

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'Hello, World!'

Flask 로 app.py 를 실행하기 위한 Dockerfile 을 준비한 뒤 build 하여 Image 를 준비합니다.

FROM python:3.7.5-slim

RUN pip install flask==1.1.1

WORKDIR /app
ADD . /app

ENV FLASK_APP app.py

ENTRYPOINT ["flask", "run", "--host=0.0.0.0"]
docker build . -t kubernetes-study

Docker Image 를 관리할 ECR Repository 를 생성합니다.

  • Repository name : kubernetes-study
  • Tag immutability : Disabled
  • Scan on push : Disabled

Step 1: Authenticate Docker to your Default Registry 문서를 참고하여 aws ecr get-login 명령어를 실행한 뒤, 획득한 docker login 명령어를 실행하여 인증합니다. 그 다음 Pushing an Image 문서를 참고하여 push 할 Image ID 를 확인한 뒤에 적절한 tag 를 달고 ECR Repository 에 push 합니다.

docker tag <image_id> <aws_account_id>.dkr.ecr.ap-northeast-2.amazonaws.com/kubernetes-study
docker push <aws_account_id>.dkr.ecr.ap-northeast-2.amazonaws.com/kubernetes-study

Kubernetes Objects 생성

Learning Kubernetes on EKS by Doing 연재글의 Part 2Part 3 글을 참고하여 Deployment 와 Service 를 정의하는 YAML 파일을 작성합니다. Service 를 만들 때 Classic Load Balancer 를 사용합니다. 작성한 뒤 kubectl 명령어를 실행해서 적용합니다. (<aws_account_id> 부분을 AWS Account ID 로 교체)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-app
  labels:
    name: flask-app
spec:
  replicas: 2
  selector:
    matchLabels:
      name: flask-app
  template:
    metadata:
      name: flask-app
      labels:
        name: flask-app
    spec:
      containers:
        - name: flask-app
          image: <aws_account_id>.dkr.ecr.ap-northeast-2.amazonaws.com/kubernetes-study:latest
          ports:
            - containerPort: 5000
          resources:
            requests:
              memory: 256Mi
            limits:
              memory: 512Mi
kubectl apply -f deployment.yaml
kubectl get pods

NAME                        READY   STATUS    RESTARTS   AGE
flask-app-cb674b795-nbf87   1/1     Running   0          38s
flask-app-cb674b795-sxnw4   1/1     Running   0          38s
apiVersion: v1
kind: Service
metadata:
  name: flask-app
spec:
  type: LoadBalancer
  selector:
    name: flask-app
  ports:
    - protocol: TCP
      port: 5000
      targetPort: 5000
kubectl apply -f service.yaml

kubectl get services 명령어를 실행하면 NAME 이 flask-app 이고 TYPE 이 LoadBalancer 인 Object 가 생성된 것을 확인할 수 있습니다. 그 Object 의 EXTERNAL-IP 값을 복사한 뒤에 앞에 http:// 을 붙이고 뒤에 :5000 port 를 지정해서 브라우저로 접속해보면, Flask 코드에 적은대로 Hello, World! 가 응답으로 내려오는 것을 확인할 수 있습니다.

레퍼런스