• AWS EKS 클러스터 구축 - 1부

    2023. 5. 11.

    by. mason.jeong

    EKS AWS의 관리형 쿠버네티스 서비스입니다. 마스터 노드가 포함되어있어 클러스터당 한달에 70 달러의 기본 요금이 책정되었습니다. 관리형 서비스이기 떄문에 API 엔드포인트만 제공하고 마스터노드로의 접근과 관리를 제한하고 있습니다. 예전에 외부 프로젝트를 진행하면서 잠시 AKS (마이크로 소프트 애저 쿠버네티스 서비스) 를 사용했었는데 그때 쿠버네티스의 강력함을 체감했습니다. 서비스에대한 디스커버리나 서비스에 맞게 노드나 컨테이너를 패킹하고 이모든 부분을 개발 문서 작성하듯이 작성하고 프로비저닝 할수 있다는점과, 개발 환경이나 프로덕트를 빠르게 구성하고 변경할 수 있다는 점에서 쿠버네티스는 개발자가 사용해야 하는구나를 많이 느꼈습니다.

     

    저는 보통 프로젝트 단위로 작업을 시작하는데 프로젝트가 시작되면 인프라에서부터 프론트 영역까지의 모든 부분을 설계 해야 하는일이 종종 있었습니다. 고객사 별로 요구사항이 조금씩 다르긴 하지만 거의 대부분을 클라우드환경에서 작업을 했습니다. 그런 경우.. 인프라를 구성하고 안정적으로 만들기위해 시간이 많이 들게 되더라구요. 물리적으로 필요한 시간이라고 생각했습니다. 컨테이너 기반이어도 마찬가지였습니다. 배포를 위한 저장소, 저장소에서 배포까지의 파이프라인, 서비스를 실행해주는 러너, 러너를 모니터링.. 해야할 일이 많았습니다. 저는 프로젝트 설계와 매니징도 해야하지만 실제 코드를 짜는 실무도 해야하기 때문에 이러한 시간을 좀 줄이고자 하는 욕구가 강했습니다.

     

    그러면서 맨 처음 ECS를 찾아 사용해봤는데요. 반 서버리스(?) 다 보니까 서버를 직접 세팅할 일도 없고 테라폼이나 AWS콘솔에서 설정만 해주면 배포판에 맞춰서 서비스를 교체해주는게 좋았습니다. 하지만 결국 ECS도 AWS의 서비스 이다 보니까 배포판을 교체하거나 롤아웃 롤백등의 경우에서 매끄럽지 못한 경우를 많이 겪게 되었습니다. 

     

    그래서 결국 EKS 를 사용해보기로 결심했고 나름대로 스터디를 해가며 실제 서비스에 적용해 보았습니다. 서론이 길었지만 아래 내용은 테라폼과 EKS 서비스를 통해 클러스터를 구성하는 과정입니다. 

     


     

    EKS 는 루트 계정이어도 클러스터의 내용이나 설정을 변경할 권한이 없습니다. 또한 기존 VPC를 이용해서 클러스터를 구성하려다가 권한 문제로 새 VPC 를 생성하여 다시 작업을 하게 되었습니다. 그래서 Cluster 를 운영할 IAM 계정을 하나 생성해주시고, 액세스 키와 시크릿 액세스 키를 미리 복사해 주세요. 콘솔에서 작업하지 않기때문에 프로그래밍 방식으로만 생성해 주어도 충분합니다.

     

    Terraform

    저는 테라폼이 너무 신세계였습니다. 프로젝트 단위로 작업을 하다보니 비슷한 스펙의 인프라를 구성해야하는 경우가 많이 있는데 테라폼은 그저 스크립트만 작성해놓으면 인프라를 거의 자동으로 생성해주니 시간적으로 여유가 많이 생겼습니다. 

     

    오픈소스이며 코드로 인프라 스트럭처를 관리한다는 개념으로 IaC라고도 하고 AWS에는 클라우드 포메이션이라는 IaC서비스도 있지만 테라폼은 아마존과 애저, 구글 클라우드 등과 같은 클라우드 서비스를 비롯하여 다양한 클라우드 서비스들을 프로비저닝 할 수 있게 도와줍니다.

     

    https://www.terraform.io/downloads

     

    Install | Terraform | HashiCorp Developer

    Explore Terraform product documentation, tutorials, and examples.

    developer.hashicorp.com

    저는 윈도우11 환경에서 테라폼을 이용했습니다. 다운로드 받으면 terraform.exe 파일만 덩그러니 있는데요 적절한 디렉토리로 옮기셔서 윈도우 환경 변수를 등록해 cmd 나 파워쉘에서 찾을수 있도록 설정해 주세요.

     

     

    AWS CLI 설치

    aws 리소스와 eks 관련 서비스를 세팅하기 위해 awscli 를 설치해주어야 합니다. 아래 링크에서 각 환경별 설치 지침에 따라 설치해주세요. 최종적으로 콘솔환경에서 aws 명령이 잘 실행 되면 됩니다.

    https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html

     

    최신 버전의 AWS CLI 설치 또는 업데이트 - AWS Command Line Interface

    이전 버전에서 업데이트하는 경우 unzip 명령을 실행하면 기존 파일을 덮어쓸지 묻는 메시지가 표시됩니다. 스크립트 자동화와 같은 경우에 이러한 프롬프트를 건너뛰려면 unzip에 대한 -u 업데이

    docs.aws.amazon.com

     

    AWS CLI 에 클러스터 루트용 IAM 계정으로 세팅을 해주세요.

    PS C:\Users\juhojeong> aws configure
    AWS Access Key ID [****************PA4H]: ## ACCESS_KEY_ID 를 넣어준다.
    AWS Secret Access Key [****************6e4c]: ## SECRET_ACCESS_KEY 를 넣어준다.
    Default region name [ap-northeast-2]: ## 리전명
    Default output format [None]:

     

     

    Kubectl 설치

    kubectl 은 콘솔에서 바로 쿠버네티스와 소통할수 있는 인터페이스 입니다. 앞으로 자주 접하게 될 명령어 이기도 합니다. https://subicura.com/k8s/prepare/kubectl-setup.html#%E1%84%89%E1%85%A5%E1%86%AF%E1%84%8E%E1%85%B5%E1%84%92%E1%85%A1%E1%84%80%E1%85%B5

     

    kubectl 설치

    쿠버네티스에 명령을 전달하기 위한 kubectl 프로그램을 설치합니다.

    subicura.com

     

     

    eksctl 설치

    EKS 는 AWS 서비스 이므로 EKS 에 관련된 설정을 하기위해 별도로 마련된 콘솔 프로그램입니다. https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/getting-started-eksctl.html

     


     

    Terraform 리소스 설정

    기본 프로그램을 모두 설치했다면 aws 리소스를 생성하기 위해 terraform 파일을 만들어 줍니다. 깃허브에 테라폼 aws 프로바이더 템플릿이 있으므로 이것을 이용하여 작성하도록 하겠습니다.

    git clone https://github.com/terraform-providers/terraform-provider-aws.git
    cd terraform-provider-aws/examples/eks-getting-started

     

    기본 terraform 프로바이더를 살펴보도록 하겠습니다. 파일 탐색기를 통해 해당 디렉토리로 접근해 주세요. 여기서 생성하는 리소스의 별칭을 my-terraform 이라고 하겠습니다.아래 파일에서 만약 이름을 다르게 하고 싶으시다면 my-terraform 에 해당하는 텍스트를 변경해 주세요.

     

    eks-cluster.tf

    resource "aws_iam_role" "my-terraform-cluster" {
      name = "terraform-eks-my-terraform-cluster"
    
      assume_role_policy = <<POLICY
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "eks.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }
    POLICY
    }
    
    resource "aws_iam_role_policy_attachment" "my-terraform-cluster-AmazonEKSClusterPolicy" {
      policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
      role       = aws_iam_role.my-terraform.name
    }
    
    resource "aws_iam_role_policy_attachment" "my-terraform-cluster-AmazonEKSVPCResourceController" {
      policy_arn = "arn:aws:iam::aws:policy/AmazonEKSVPCResourceController"
      role       = aws_iam_role.my-terraform.name
    }
    
    resource "aws_security_group" "my-terraform-cluster" {
      name        = "terraform-eks-my-terraform-cluster"
      description = "Cluster communication with worker nodes"
      vpc_id      = aws_vpc.my-terraform.id
    
      egress {
        from_port   = 0
        to_port     = 0
        protocol    = "-1"
        cidr_blocks = ["0.0.0.0/0"]
      }
    
      tags = {
        Name = "my-terraform-eks"
      }
    }
    
    resource "aws_security_group_rule" "my-terraform-cluster-ingress-workstation-https" {
      cidr_blocks       = [local.workstation-external-cidr]
      description       = "Allow workstation to communicate with the cluster API Server"
      from_port         = 443
      protocol          = "tcp"
      security_group_id = aws_security_group.my-terraform-cluster.id
      to_port           = 443
      type              = "ingress"
    }
    
    resource "aws_eks_cluster" "osc" {
      name     = var.my-terraform-cluster
      role_arn = aws_iam_role.osc-cluster.arn
    
      vpc_config {
        security_group_ids = [aws_security_group.my-terraform-cluster.id]
        subnet_ids         = aws_subnet.my-terraform[*].id
      }
    
      depends_on = [
        aws_iam_role_policy_attachment.my-terraform-cluster-AmazonEKSClusterPolicy,
        aws_iam_role_policy_attachment.my-terraform-cluster-AmazonEKSVPCResourceController,
      ]
    }

     

    eks-worker-nodes.tf

    resource "aws_iam_role" "my-terraform-node" {
      name = "terraform-eks-my-terraform-node"
    
      assume_role_policy = <<POLICY
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "ec2.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }
    POLICY
    }
    
    resource "aws_iam_role_policy_attachment" "my-terraform-node-AmazonEKSWorkerNodePolicy" {
      policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
      role       = aws_iam_role.my-terraform-node.name
    }
    
    resource "aws_iam_role_policy_attachment" "my-terraform-node-AmazonEKS_CNI_Policy" {
      policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
      role       = aws_iam_role.my-terraform-node.name
    }
    
    resource "aws_iam_role_policy_attachment" "my-terraform-node-AmazonEC2ContainerRegistryReadOnly" {
      policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
      role       = aws_iam_role.my-terraform-node.name
    }
    
    resource "aws_eks_node_group" "my-terraform" {
      cluster_name    = aws_eks_cluster.my-terraform.name
      node_group_name = "my-terraform"
      node_role_arn   = aws_iam_role.my-terraform-node.arn
      subnet_ids      = aws_subnet.my-terraform[*].id
    
      scaling_config {
        desired_size = 1
        max_size     = 1
        min_size     = 1
      }
    
      depends_on = [
        aws_iam_role_policy_attachment.my-terraform-node-AmazonEKSWorkerNodePolicy,
        aws_iam_role_policy_attachment.my-terraform-node-AmazonEKS_CNI_Policy,
        aws_iam_role_policy_attachment.my-terraform-node-AmazonEC2ContainerRegistryReadOnly,
      ]
    }

     

    eks-worker-nodes 는 이름에서 알수 있듯 워커 노드에 대한 IAM role과 노드그룹, 오토스케일, 등의 값을 설정할 수 있습니다.

     

    outputs.tf

    locals {
      config_map_aws_auth = <<CONFIGMAPAWSAUTH
    
    
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: aws-auth
      namespace: kube-system
    data:
      mapRoles: |
        - rolearn: ${aws_iam_role.my-terraform-node.arn}
          username: system:node:{{EC2PrivateDNSName}}
          groups:
            - system:bootstrappers
            - system:nodes
    CONFIGMAPAWSAUTH
    
      kubeconfig = <<KUBECONFIG
    
    
    apiVersion: v1
    clusters:
    - cluster:
        server: ${aws_eks_cluster.my-terraform.endpoint}
        certificate-authority-data: ${aws_eks_cluster.my-terraform.certificate_authority[0].data}
      name: kubernetes
    contexts:
    - context:
        cluster: kubernetes
        user: aws
      name: aws
    current-context: aws
    kind: Config
    preferences: {}
    users:
    - name: aws
      user:
        exec:
          apiVersion: client.authentication.k8s.io/v1beta1
          command: aws-iam-authenticator
          args:
            - "token"
            - "-i"
            - "${var.cluster-name}"
    KUBECONFIG
    }
    
    output "config_map_aws_auth" {
      value = local.config_map_aws_auth
    }
    
    output "kubeconfig" {
      value = local.kubeconfig
    }

     

    outputs 는 해당 파일에 설정된 값을 통해 EKS 배포 완료 후 항목들을 확인하여 정상 배포되었음을 판단합니다. 

     

    providers.tf

    terraform {
      required_version = ">= 0.12"
    }
    
    provider "aws" {
      region = var.aws_region
      access_key = "ACCESS_KEY"
      secret_key = "SECRET_KEY"
    }
    
    data "aws_availability_zones" "available" {}
    
    # Not required: currently used in conjunction with using
    # icanhazip.com to determine local workstation external IP
    # to open EC2 Security Group access to the Kubernetes cluster.
    # See workstation-external-ip.tf for additional information.
    provider "http" {}

     

    providers 에서는 EKS 를 생성할 AWS Key 관련 값이 있습니다. 여기서 복사해두신 AWS IAM 액세스 키와 시크릿 액세스 키를 입력해주세요.

     

    variables.tf

    variable "aws_region" {
      default = "ap-northeast-2"
    }
    
    variable "cluster-name" {
      default = "my-terraform-eks"
      type    = string
    }

     

    variables 는 말그대로 여러가지 변수를 설정할 수 있습니다. 이번에는 EKS 를 생성할 리전과 클러스터 이름값을 설정했습니다.

     

    vpc.tf

    resource "aws_vpc" "my-terraform" {
      cidr_block = "10.0.0.0/16"
    
      tags = tomap({
        "Name"                                      = "my-terraform-eks-node",
        "kubernetes.io/cluster/${var.cluster-name}" = "shared",
      })
    }
    
    resource "aws_subnet" "my-terraform" {
      count = 2
    
      availability_zone       = data.aws_availability_zones.available.names[count.index]
      cidr_block              = "10.0.${count.index}.0/24"
      map_public_ip_on_launch = true
      vpc_id                  = aws_vpc.my-terraform.id
    
      tags = tomap({
        "Name"                                      = "my-terraform-eks-node",
        "kubernetes.io/cluster/${var.cluster-name}" = "shared",
      })
    }
    
    resource "aws_internet_gateway" "my-terraform" {
      vpc_id = aws_vpc.my-terraform.id
    
      tags = {
        Name = "my-terraform-eks"
      }
    }
    
    resource "aws_route_table" "my-terraform" {
      vpc_id = aws_vpc.my-terraform.id
    
      route {
        cidr_block = "0.0.0.0/0"
        gateway_id = aws_internet_gateway.my-terraform.id
      }
    }
    
    resource "aws_route_table_association" "my-terraform" {
      count = 2
    
      subnet_id      = aws_subnet.my-terraform.*.id[count.index]
      route_table_id = aws_route_table.my-terraform.id
    }

     

    vpc 에서는 생성하는 EKS 가 사용할 네트워크 환경을 구성합니다. VPC는 다른 리소스 등의 VPC와 동일해야 하기 때문에 새로 만드는 경우 모든 리소스를 새로 생성해 주어야 합니다.

     


     

    EKS 배포 시작

    파일이 이상없이 설정되었다면 아래와 같이 테라폼을 실행시켜 배포를 시작합니다. 

    PS> terraform init
    ...
    Terraform has been successfully initialized!
    
    You may now begin working with Terraform. Try running "terraform plan" to see
    any changes that are required for your infrastructure. All Terraform commands
    should now work.
    
    If you ever set or change modules or backend configuration for Terraform,
    rerun this command to reinitialize your working directory. If you forget, other
    commands will detect it and remind you to do so if necessary.
    
    PS> terraform apply
    ...
    Apply complete! Resources: 18 added, 0 changed, 0 destroyed.

     

    배포 후 EKS 콘솔로 로그인 해보면 아래와 같이 생성된 클러스터를 확인할 수 있습니다.

     

    쿠버네티스 명령어를 사용하기 위해서 EKS kubeconfig 파일을 받아주어야 합니다. 아래와 같이 설정합니다.

    PS> aws eks update-kubeconfig --region ap-northeast-2 --name my-terraform-eks
    Added new context arn:aws:eks:ap-northeast-2:523296135686:cluster/my-terraform-eks to /Users/jeongjuho/.kube/config
    
    PS> kubectl get nodes
    NAME                                           STATUS   ROLES    AGE     VERSION
    ip-10-0-1-62.ap-northeast-2.compute.internal   Ready    <none>   4m29s   v1.24.9-eks-49d8fe8

    ec2 콘솔에서도 아래와 같이 ec2 인스턴스가 하나 생성된 것을 확인할 수 있습니다.

     

     


     

    ACM 인증서 생성

    EKS 에서 Ingress를 통해 서비스를 외부에 제공할 떄 TLS 암호화를 통해 https 를 구현해 줄 수 있습니다. 해당 arn 은 nginx controller 를 설정할때 사용하므로 메모장에 복사 해주세요. 아래와 같이 명령어를 입력합니다.

    PS> aws acm request-certificate \
    --domain-name www.my-terraform-web.com \
    --validation-method DNS \
    --idempotency-token 1234 \
    --options CertificateTransparencyLoggingPreference=DISABLED
    
    ...
    
    {
        "CertificateArn": "arn:aws:acm:region:account:certificate/certificate_ID"
    }

     


     

    NginxController 배포 및 설정

    EKS 의 서비스에 외부 액세스를 제공하기위해 AWS는 자체 서비스인 로드밸런서를 이용하여 제공할 수 있습니다. EKS 에서 로드밸런서를 컨트롤 하는 컨테이너를 하나 생성해 주면 ingress 를 통해 외부 액세스를 제공할 수 있습니다.

     

    alb 를 이용한 로드밸런서를 사용할 수 있지만 alb를 사용하면 서브도메인이 다른 여러 서비스 게이트웨이를 사용할 수 없으므로 nlb 를 이용한 컨트롤러를 사용하여 서브도메인에 따라 서비스를 분기처리 할 수 있도록 구성하겠습니다.

     

    aws에서 기본 제공하는 nginx controller 템플릿을 다운로드 합니다.

    PS> wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml

     

    다운로드 받은 파일을 열어 아래 내용을 수정합니다.

    service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "60"
    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: 생성한_ACM_ARN
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: https
    service.beta.kubernetes.io/aws-load-balancer-type: nlb

     

     

    클러스터에 대한 VPC CIDR 을 변경해주세요. CIDR 은 클러스터의 VPC에서 확인할 수 있습니다.

    proxy-real-ip-cidr: 172.31.0.0/16

     

    수정된 매니페스트를 쿠버네티스에 적용합니다.

    PS> kubectl apply -f deploy.yml
    namespace/ingress-nginx created
    serviceaccount/ingress-nginx created
    serviceaccount/ingress-nginx-admission created
    role.rbac.authorization.k8s.io/ingress-nginx created
    role.rbac.authorization.k8s.io/ingress-nginx-admission created
    clusterrole.rbac.authorization.k8s.io/ingress-nginx created
    clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
    rolebinding.rbac.authorization.k8s.io/ingress-nginx created
    rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
    clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
    clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
    configmap/ingress-nginx-controller created
    service/ingress-nginx-controller created
    service/ingress-nginx-controller-admission created
    deployment.apps/ingress-nginx-controller created
    job.batch/ingress-nginx-admission-create created
    job.batch/ingress-nginx-admission-patch created
    ingressclass.networking.k8s.io/nginx created
    validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created

     

    적용 후 배포된 리소스를 확인합니다.

    PS> kubectl get all -n ingress-nginx --selector app.kubernetes.io/instance=ingress-nginx
    NAME                                            READY   STATUS      RESTARTS   AGE
    pod/ingress-nginx-admission-create-vcxgx        0/1     Completed   0          36s
    pod/ingress-nginx-admission-patch-xmswt         0/1     Completed   0          36s
    pod/ingress-nginx-controller-8594c5cbcb-ppt65   1/1     Running     0          36s
    
    NAME                                         TYPE           CLUSTER-IP      EXTERNAL-IP                                                                          PORT(S)                      AGE
    service/ingress-nginx-controller             LoadBalancer   172.20.28.176   a2c1e1dab574e405daea97ac0229e99b-da9c7f53e0502d31.elb.ap-northeast-2.amazonaws.com   80:30976/TCP,443:32413/TCP   36s
    service/ingress-nginx-controller-admission   ClusterIP      172.20.85.253   <none>                                                                               443/TCP                      36s
    
    NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/ingress-nginx-controller   1/1     1            1           36s
    
    NAME                                                  DESIRED   CURRENT   READY   AGE
    replicaset.apps/ingress-nginx-controller-8594c5cbcb   1         1         1       36s
    
    NAME                                       COMPLETIONS   DURATION   AGE
    job.batch/ingress-nginx-admission-create   1/1           7s         36s
    job.batch/ingress-nginx-admission-patch    1/1           7s         36s

     

    IngressClass가 잘 생성되었는지도 체크해줍니다.

    PS> kubectl get ingressclass
    NAME    CONTROLLER             PARAMETERS   AGE
    nginx   k8s.io/ingress-nginx   <none>       83s

     

    WEB 서비스 생성 및 배포

    python을 사용하여 간단한 웹 서비스를 만들어주겠습니다. web-server 디렉토리를 하나 생성하고 아래와 같이 코드를 작성해 주세요.

     

    server.py

    from flask import Flask
    app = Flask(__name__)
    
    @app.route('/hello')
    def hello():
        return 'Hellow world!'
    
    if __name__ == '__main__':
        app.run(host="0.0.0.0")

     

    노드에 올라갈 컨테이너 이미지를 만들어줍니다.

    FROM python:3.8
    
    RUN pip install flask
    RUN pip install httplib2
    RUN pip install requests
    
    WORKDIR /app
    
    ADD server.py .
    
    CMD ["python3", "-u", "server.py"]

     

    이미지를 빌드하여 레지스트리로 배포해 줍니다.

    PS> docker build -t reg.my-harbor-repo.com/my-terraform/web:1.0 .
    PS> docker push reg.my-harbor-repo.com/my-terraform/web:1.0

     

    EKS 배포가 될때 만약 Private 저장소를 이용하고 있고, 인증이 필요한 레지스트리라면 아래와 같이 Secret을 추가하여 저장소 인증을 대신할 수 있습니다.

    PS> kubectl create secret docker-registry harbor --docker-server=reg.my-harbor-repo.com --docker-username=로그인아이디 --docker-password=비밀번호 --docker-email=이메일

     

    EKS에 배포될 deployment와 서비스를 생성합니다.

     

    deployment.yml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: webserver
      labels:
        app: web
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: web
      template:
        metadata:
          labels:
            app: web
        spec:
        	imagePullSecrets:
            - name: harbor
          containers:
          - name: webserver
            image: reg.my-harbor-repo.com/my-terraform/web:1.0
            imagePullPolicy: Always
            ports:
            - containerPort: 5000
              name: flask
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: webserver-service
    spec:
      type: NodePort
      selector:
        app: web
      ports:
        - port: 5000
          targetPort: 5000

     

    deployment와 service를 배포하고 팟이 잘 동작중인지 확인합니다.

    PS> kubectl apply -f deployment.yml
    deployment.apps/webserver created
    service/webserver-service created
    
    PS> kubectl get pods
    NAME                         READY   STATUS    RESTARTS   AGE
    webserver-6d869fc594-s94wb   1/1     Running   0          100s

     

    NginxIngress 설정

    EKS 의 서비스에 대한 Ingress를 설정하여 외부 연결을 열어줍니다. 

     

    ingress.yml

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: ingress-backend
      annotations:
        kubernetes.io/ingress.class: "nginx"
    spec:
      rules:
        - host: www.my-terraform-web.com
          http:
            paths:
              - backend:
                  service:
                    name: webserver-service
                    port:
                      number: 5000
                path: /
                pathType: Prefix
        - host: my-terraform-web.com
          http:
            paths:
              - backend:
                  service:
                    name: webserver-service
                    port:
                      number: 5000
                path: /
                pathType: Prefix

     

    Ingress 가 잘 배포되었는지 확인해주세요.

    PS> kubectl apply -f ingress.yml
    ingress.networking.k8s.io/ingress-backend created
    
    PS> kubectl get ing
    NAME              CLASS    HOSTS                                           ADDRESS                                                                              PORTS   AGE
    ingress-backend   <none>   www.my-terraform-web.com,my-terraform-web.com   a2c1e1dab574e405daea97ac0229e99b-da9c7f53e0502d31.elb.ap-northeast-2.amazonaws.com   80      108s

     

    이제 브라우저를 열고 주소창에 https://www.my-terraform-web.com/hello 주소로 접근하면 방금 만든 플라스크 웹서버 화면을 볼 수 있습니다. (작성중에는 ACM DNS 인증을 진행하지 않아 https 오류가 발생했습니다.)

     

     

     

    여기까지 1부를 정리했습니다. 자세한 설명없이 순간 순간 지나간것 같은데 글을 쓰는것도 보통일이 아니네요. 만약 부족한 부분이 있다면 댓글로 알려주세요. 제가 아는 선에서 답변 드리도록 하겠습니다.

     

    2부에서 EFS와 EKS 를 사용해서 스토리지를 프로비저닝 하는 방법부터, 클러스터 운영까지 다뤄보도록 하겠습니다. 또한 지금은 클러스터 설정 파일을 모두 수동으로 작성하고 있지만 helm 이라는 설정 저장소에서 모든 설정을 관리할 수도 있습니다. 다음편에서 해당 부분까지 다뤄보도록 하겠습니다.

     

     

    'Tech > DevOps' 카테고리의 다른 글

    웹서버 오류 - bind() to[::]:443 failed 에러와 대처방법  (0) 2023.05.24

    댓글