Fall in IT.

Amazon EKS에 컨테이너 웹 앱 배포 본문

Amazon Web Service(AWS)

Amazon EKS에 컨테이너 웹 앱 배포

D.Y 2021. 11. 28. 14:09

소개

AWS CDK를 사용해서 클러스터를 생성(프로비저닝)하고 CDK8s로 생성된 매니페스트 파일을 배포, kubectl 을 사용하여 애플리케이션 운영하는 방법을 소개한다. (아래에서 작업한 소스코드)

배울 내용

  1. Amazon EKS를 사용하여 단일테넌트 제어 영역이 포함 된 Kubernetes 클러스터를 생성하고 관리형 Amazon EC2 작업자 노드를 시작한다
  2. AWS CDK를 사용하여 Kubernetes 클러스터를 위한 코드형 인프라(IaC)를 구현한다
  3. AWS CDK8S 및 AWS CDK를 통합하여 애플리케이션을 배포한다
  4. kubectl 명령어를 사용하여 클러스터를 운영한다

사전 요구사항


Chapter 1. EKS 클러스터 생성

배울 내용

  1. Amazon EC2를 작업자 노드로 사용하는 Amazon EKS 클러스터를 생성하기 위한 AWS CDK 애플리케이션 구축
  2. Kubernetes 클러스터에 대한 기본적인 작업 테스트 및 수행

구현

AWS CDK 애플리케이션 구축

  1. 작업 환경 준비
# 작업 폴더를 준비
mkdir eks
cd eks

# cluster 디렉터리는 클러스터 생성을 위한 CDK 코드가 생성될 것이고
# cdk8s 디렉터리는 cdk8s를 사용하여 애플리케이션을 생성하고 배포하는 코드가 포함될 것이다.
mkdir cluster cdk8s
cd cluster

# python 언어를 사용하는 cdk 프로젝트 생성
cdk init app --language=python
  1. 환경 설정
python3 -m venv .venv
  1. 필요한 모듈 정의
# cdk 버전을 확인하고 cdk 버전과 일치하는 라이브러리를 다운받는다
cdk --version

# eks/cluster/requirements.txt를 열고 다음 줄을 추가한다
aws_cdk.core==1.121.0

# 이 모듈에서 생성해야하는 기본 리소스 2개 AWS cluster, AWS iam
aws_cdk.aws-iam==1.121.0
aws_cdk.aws-eks==1.121.0

# 배포 단계에 필요한 라이브러리
aws_cdk.aws_ec2==1.121.0
pyyaml
  1. 필요한 모듈 설치
pip3 install -r requirements.txt
  1. CDK IAM, Cluster 정의 eks/cluster/cluster_stack.py를 열고 아래 코드 추가
from aws_cdk import core as cdk
from aws_cdk import aws_iam as iam
from aws_cdk import aws_eks as eks
from aws_cdk import aws_ec2 as ec2

class ClusterStack(cdk.Stack):

    def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Look up the default VPC
        vpc = ec2.Vpc.from_lookup(self, id="VPC", is_default=True)

        # Create master role for EKS Cluster
        iam_role = iam.Role(self, id=f"{construct_id}-iam",
                            role_name=f"{construct_id}-iam", assumed_by=iam.AccountRootPrincipal())

        # Creating Cluster with EKS
        eks_cluster = eks.Cluster(
            self, id=f"{construct_id}-cluster", 
            cluster_name=f"{construct_id}-cluster", 
            vpc=vpc, 
            vpc_subnets=vpc.public_subnets, 
            masters_role=iam_role, 
            default_capacity_instance=ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO), 
            version=eks.KubernetesVersion.V1_20,
        )
  1. 배포시 사용할 AWS 계정 ID와 region을 확인하도록 CDK 구성 eks/cluster/app.py에서 아래 코드 주석 해제 (여기서는 AWS CLI에 구성된 계정 ID와 region을 사용한다)
env=core.Environment(account=os.getenv('CDK_DEFAULT_ACCOUNT'), region=os.getenv('CDK_DEFAULT_REGION')),
  1. CDK를 사용하기 전에 부트스트랩을 한다
cdk bootstrap
  1. 클러스터 배포
cdk deploy 
  1. 결과 클러스터가 생성되면 해당 클러스터를 가리키도록 kubeconfig를 업데이트 해야한다. 아래 명령어를 복사해서 실행시켜보자
Outputs:
ClusterStack.ClusterStackclusterConfigCommand1CAA6E63 = aws eks update-kubeconfig --name ClusterStack-cluster --region ap-northeast-2 --role-arn arn:aws:iam::012634413971:role/ClusterStack-iam
ClusterStack.ClusterStackclusterGetTokenCommand010D10BE = aws eks get-token --cluster-name ClusterStack-cluster --region ap-northeast-2 --role-arn arn:aws:iam::012634413971:role/ClusterStack-iam
  1. 확인
kubectl get all

Chapter 2. CDK8s CLI 설치 (배포 준비)

CDK8S 소개

CDK8s는 익숙한 프로그래밍 언어와 다양한 객체지향 api를 사용하여 Kubernetes 애플리케이션 및 재사용 가능한 추상화를 정의하기위한 소프트웨어 개발 프레임워크이다.

CDK8s를 사용하여 애플리케이션 서비스 및 배포구성 파일을 정의한다. CDK와는 별개의 도구이며 AWS CDK8s의 출력은 Kubernetes 구성파일(Yaml)이며 kubectl 또는 AWS CDK를 사용해서 이 구성파일을 사용할 수 있다.

배울 내용

  1. CDK8s 애플리케이션 부트스트랩을 위한 pipenv 설치
  2. CDK8s CLI 설치

구현

  1. CDK8s 설치
npm i -g cdk8s-cli
  1. pipenv 설치 CDK8s는 Python기반 프로젝트에 pipenv를 ㅅ용한다. pipenv는 python 개발 프로세스를 단일 명령줄 도구로 통합하여 간소화한다
pip3 install pipenv 
  1. CDK8s 애플리케이션 생성
cd cdk8s

cdk init python-app

Chapter 3. 배포를 위한 구성파일 생성

배울 내용

  • CDK8s 구문을 사용하여 Kubernetes API 객체 정의
  • CDK8s를 사용하여 서비스 및 배포 정의
  • CDK8s를 사용하여 Kubernetes 구성 생성

구현

애플리케이션 배포하려면 4단계가 필요하다.

  1. Yaml 구성 파일에 대한 문자열을 생성하는데 도움이 되는 k8s 라이브러리를 가져온다.
  2. 서비스 조회에 사용할 포드에 적용할 레이블 세트를 정의한다.
  3. 배포를 정의한다. 배포를 정의하면 클러스터의 컨테이너가 구동되지만 로드 밸런서의 트래픽을 수신하도록 구성되지는 않는다.
  4. 로드밸런서에 배포를 노출하기 위한 서비스를 정의한다.

레이블은 Kubernetes 객체에 연결되는 키/값 페어다. 배포 중에 실행할 포드를 태깅한다. ReplicationController는 로드 밸런서에 노출하기 위한 서비스를 생성할 때 동일한 레이블을 사용하여 포드를 선택한다. 이 작업을 위해 label = {"app": "cdk8s"} 코드를 사용한다.

Kubernetes에서 배포는 배포 단위 및 원하는 상태를 명시적으로 선언하는 것이다. 이 가이드에서는 Amazon ECR 퍼블릭 갤러리에서 호스트 되는 샘플 애플리케이션을 사용한다.

  1. 서비스와 배포 구성파일을 만들기위한 준비 cdk8s/main.py 아래 코드 복사
#!/usr/bin/env python
from constructs import Construct
from cdk8s import App, Chart
from imports import k8s

class MyChart(Chart):
    def __init__(self, scope: Construct, id: str):
        super().__init__(scope, f"{id}-deployment")

        # define resources here

        # Label used for tagging pods to link in the service
        label = {"app": "cdk8s"}

        # Creates the deployment to spin up pods with your container
        k8s.KubeDeployment(self, 'deployment',
            spec=k8s.DeploymentSpec(
                replicas=2,
                selector=k8s.LabelSelector(match_labels=label),
                template=k8s.PodTemplateSpec(
                metadata=k8s.ObjectMeta(labels=label),
                spec=k8s.PodSpec(containers=[
                    k8s.Container(
                    name='cdk8s',
                    image='public.ecr.aws/s9u7u6x1/sample_app_001:no-db',
                    ports=[k8s.ContainerPort(container_port=80)])]))))

        # Creates the service to expose the pods to traffic from the loadbalancer
        super().__init__(scope, f"{id}-service")
        k8s.KubeService(self, 'service',
            spec=k8s.ServiceSpec(
            type='LoadBalancer',
            ports=[k8s.ServicePort(port=80, target_port=k8s.IntOrString.from_number(80))],
            selector=label))

app = App()
MyChart(app, "cdk8s")

app.synth()
  1. 구성 파일(yaml) 생성
cdk8s synth

# Output: dist/cdk8s-deployment.k8s.yaml, dist/cdk8s-service.k8s.yaml

Chapter 4. AWS CDK로 배포

소개

이전에 CDK8s를 통해 만든 구성파일을 사용하여 EKS 클러스터에 애플리케이션을 배포한다.

배울 내용

  • AWS CDK에 AWS CDK8s 통합
  • AWS CDK를 사용하여 배포
  • Kubectl로 클러스터 운영

구현

  1. CDK에서 kubernetes 구성파일을 읽어온다.
# Read the deployment config
with open("../cdk8s/dist/cdk8s-deployment.k8s.yaml", 'r') as stream:
      deployment_yaml = yaml.load(stream, Loader=yaml.FullLoader)

# Read the service config
with open("../cdk8s/dist/cdk8s-service.k8s.yaml", 'r') as stream:
      service_yaml = yaml.load(stream, Loader=yaml.FullLoader)
  1. add_manifest 메서드를 사용해서 yaml을 EKS 클러스터에 전달한다.
eks_cluster.add_manifest(f"{construct_id}-app-deployment", yaml_app_deployment)

eks_cluster.add_manifest(f"{construct_id}-app-service", yaml_app_service)
  1. 최종 cluster_stack.py 코드
from aws_cdk import core as cdk
from aws_cdk import aws_iam as iam
from aws_cdk import aws_eks as eks
from aws_cdk import aws_ec2 as ec2
import yaml

class ClusterStack(cdk.Stack):

    def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Look up the default VPC
        vpc = ec2.Vpc.from_lookup(self, id="VPC", is_default=True)

        # Create master role for EKS Cluster
        iam_role = iam.Role(self, id=f"{construct_id}-iam",
                            role_name=f"{construct_id}-iam", assumed_by=iam.AccountRootPrincipal())

        # Creating Cluster with EKS
        eks_cluster = eks.Cluster(
            self, id=f"{construct_id}-cluster", 
            cluster_name=f"{construct_id}-cluster", 
            vpc=vpc, 
            vpc_subnets=vpc.public_subnets, 
            masters_role=iam_role, 
            default_capacity_instance=ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO), 
            version=eks.KubernetesVersion.V1_20,
        )

# Read the deployment config
with open("../cdk8s/dist/cdk8s-deployment.k8s.yaml", 'r') as stream:
      deployment_yaml = yaml.load(stream, Loader=yaml.FullLoader)

# Read the service config
with open("../cdk8s/dist/cdk8s-service.k8s.yaml", 'r') as stream:
      service_yaml = yaml.load(stream, Loader=yaml.FullLoader)

eks_cluster.add_manifest(f"{construct_id}-app-deployment", deployment_yaml)

eks_cluster.add_manifest(f"{construct_id}-app-service", service_yaml)
  1. 애플리케이션 배포
# eks/cluster 경로에서 실행
cdk deploy
  1. 배포 확인
kubectl get all



Chapter 5. 리소스 정리

배울 내용

  • CDK 애플리케이션을 통해 생성된 AWS 리소르를 제거하는 방법
cdk destroy

참조

소스코드, https://github.com/leeduyoung/aws-cdk-tutorial/tree/master/eks
AWS deploy-webapp-eks, https://aws.amazon.com/ko/getting-started/guides/deploy-webapp-eks/

cdk8s, https://cdk8s.io/docs/latest/getting-started/

AWS 계정, https://aws.amazon.com/ko/getting-started/guides/setup-environment/

Comments