안녕하세요 오픈소스컨설팅에서 클라우드 엔지니어 업무를 수행하고 있는 인수영입니다.
들어가면서
요즘 IT시장에서 핵심 기술로 대두되고 있는 컨테이너 기술은 계속해서 꾸준히 발전하고 있으며,
Private 및 Public 환경에서 많은 사람들이 Kubernetes를 이용하기도하고, 도입하기 위해 시도하고
있습니다.
이 포스팅에서는 Amazon에서 Kuberntes를 구축하시려는 분들이 누구나 손 쉽게 따라하실 수 있도록 Amazone EKS 환경 구축 방법을 기준으로 내용을 다루어 보겠습니다.
EKS는 뭘까요?
Elastic Kubernetes Service의 약자로, AWS에서 지원하는 Kubernetes 서비스입니다.
EKS는 어떻게 배포할 수 있나요?
- 클라우드에서 Amazon EKS 실행
- EC2 배포방식
- Fargate 배포방식
- AWS Outposts에서 Amazon EKS 실행
- AWS EKS Anywhere 실행
크게 총 3가지의 배포 방식이 있으며, 이번 포스팅에서는 “클라우드에서 Amazon EKS 실행”의 EC2 배포방식에 대해서 다뤄볼 것입니다.
사전 준비 사항으로 AWS 계정과, 외부 통신이 가능한 서버 또는 VM이 필요합니다.
저는 외부랑 통신이 가능한 Ubuntu를 준비했고 console이라는 hostname을 가지고 있습니다.
AWS Console에서의 EKS Cluster 배포 준비
먼저 EKS 배포하기 위해 AWS Console의 IAM을 통해 사용자를 추가하겠습니다.
저희는 AWS CLI를 통해 명령어를 수행할 것이기 때문에 AWS 액세스 유형을 자격 증명을 액세스 키로 선택하겠습니다.
사용자는 EKS를 관리하기 위한 권한정책을 가져야하며, 권한정책은 클러스터 관리, 노드, Pod 실행 등 무수히 많은 정책으로 세밀하게 관리할 수 있습니다. 이 포스트에서는 편의상 AdministratorAccess 권한을 부여하도록 하겠습니다.
Note. 실 운영을 필요로하는 기업이나, 고객사들에서는 경험 상 AdministratorAccess 권한을 부여해주지 않습니다. 그렇기 때문에 사전에 EKS 배포를 위해서 필요한 권한정책을 하나하나 확인해가는 것이 필요합니다.
태그는 선택사항으로 별도로 지정하지 않습니다.
사용자 생성 프로시저를 통한 입력값을 한번 더 검토합니다.
사용자는 생성완료 되었으며, 액세스 키 ID와 비밀 액세스 키 ID는 별도로 기입해두도록 합니다.
외부 VM에서의 EKS Cluster 배포 준비
이제 EKS를 배포할 차례입니다.
배포 방법은 Terraform을 사용하는 방법도 있고, AWS CLI를 통해 배포하는 방법도 있으며,
이 포스트에서는 저희는 Terraform을 이용하여 배포하도록 하겠습니다.
먼저 사전에 준비해 둔 외부 통신 가능한 서버 또는 VM에 접속하여 필요한 패키지 다운로드 및 설치,
구성을 해야 합니다.
아래 순서대로 따라오시면 문제 없이 진행될 것이라고 생각됩니다.
필수 패키지 설치 및 구성파일 설정
첫번째, Terraform 명령어를 설치해줍니다.
root@console:~# apt-get update && sudo apt-get install -y gnupg software-properties-common root@console:~# wget -O- https://apt.releases.hashicorp.com/gpg | \ gpg --dearmor | \ sudo tee > /usr/share/keyrings/hashicorp-archive-keyring.gpg root@console:~# gpg --no-default-keyring \ --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg \ --fingerprint root@console:~# echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \ https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \ sudo tee > /etc/apt/sources.list.d/hashicorp.list root@console:~# apt update root@console:~# apt-get install terraform root@console:~# terraform --version Terraform v1.3.1 on linux_amd64
두번째 AWS 명령어를 사용하기 위해 awscli를 설치해 줍니다.
root@console:~/awscli# curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 44.9M 100 44.9M 0 0 37.4M 0 0:00:01 0:00:01 --:--:-- 37.4M root@console:~/awscli# unzip awscliv2.zip Archive: awscliv2.zip ... root@console:~/awscli# sudo ./aws/install You can now run: /usr/local/bin/aws --version root@console:~/awscli# aws --version aws-cli/2.8.0 Python/3.9.11 Linux/5.4.0-126-generic exe/x86_64.ubuntu.20 prompt/off
세번째로 eks 관리를 위해 eksctl 명령어를 설치해 줍니다.
root@console:~# curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp root@console:~# sudo mv /tmp/eksctl /usr/local/bin root@console:~# eksctl version 0.113.0
이제는 Terraform을 이용한 EKS 배포를 위해 환경변수 파일들을 다운로드 받고, 필요한 파일을 가져오도록 하겠습니다.
root@console:~# git clone https://github.com/terraform-providers/terraform-provider-aws.git Cloning into 'terraform-provider-aws'... remote: Enumerating objects: 416992, done. remote: Counting objects: 100% (5/5), done. remote: Compressing objects: 100% (4/4), done. remote: Total 416992 (delta 1), reused 2 (delta 1), pack-reused 416987 Receiving objects: 100% (416992/416992), 395.62 MiB | 19.03 MiB/s, done. Resolving deltas: 100% (299475/299475), done. Updating files: 100% (10131/10131), done. root@console:~# cd terraform-provider-aws/ root@console:~/terraform-provider-aws# ls CHANGELOG.md LICENSE ROADMAP.md examples go.sum internal mkdocs.yml skaff tools website GNUmakefile README.md docs go.mod infrastructure main.go names terraform-registry-manifest.json version root@console:~/terraform-provider-aws# cd examples/eks-getting-started/ root@console:~/terraform-provider-aws/examples/eks-getting-started# ls README.md eks-cluster.tf eks-worker-nodes.tf outputs.tf providers.tf variables.tf vpc.tf workstation-external-ip.tf root@console:~# cp -rp /root/terraform-provider-aws/examples/eks-getting-started /root/aws-eks
EKS 배포를 위한 구성파일은 .tf 확장자를 가지고 있으며, 모두 Terraform 스크립트이며, 파일을 하나씩 살펴보겠습니다.
eks-clsuter.tf: EKS 클러스터에 필요한 IAM role과 SecurityGroup, EKS 클러스터 대한 값이 있습니다.
resource "aws_iam_role" "osc-cluster" { name = "terraform-eks-osc-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" "osc-cluster-AmazonEKSClusterPolicy" { policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy" role = aws_iam_role.osc-cluster.name } resource "aws_iam_role_policy_attachment" "osc-cluster-AmazonEKSVPCResourceController" { policy_arn = "arn:aws:iam::aws:policy/AmazonEKSVPCResourceController" role = aws_iam_role.osc-cluster.name } resource "aws_security_group" "osc-cluster" { name = "terraform-eks-osc-cluster" description = "Cluster communication with worker nodes" vpc_id = aws_vpc.osc.id egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "terraform-eks-osc" } } resource "aws_security_group_rule" "osc-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.osc-cluster.id to_port = 443 type = "ingress" } resource "aws_eks_cluster" "osc" { name = var.cluster-name role_arn = aws_iam_role.osc-cluster.arn vpc_config { security_group_ids = [aws_security_group.osc-cluster.id] subnet_ids = aws_subnet.osc[*].id } depends_on = [ aws_iam_role_policy_attachment.osc-cluster-AmazonEKSClusterPolicy, aws_iam_role_policy_attachment.osc-cluster-AmazonEKSVPCResourceController, ] }
eks-worker-nodes.tf: EKS Worker 노드에 대한 IAM role과 NodeGroup AutoScale, NodeGroup 값이
있습니다.
resource "aws_iam_role" "osc-node" { name = "terraform-eks-osc-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" "osc-node-AmazonEKSWorkerNodePolicy" { policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy" role = aws_iam_role.osc-node.name } resource "aws_iam_role_policy_attachment" "osc-node-AmazonEKS_CNI_Policy" { policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" role = aws_iam_role.osc-node.name } resource "aws_iam_role_policy_attachment" "osc-node-AmazonEC2ContainerRegistryReadOnly" { policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" role = aws_iam_role.osc-node.name } resource "aws_eks_node_group" "osc" { cluster_name = aws_eks_cluster.osc.name node_group_name = "osc" node_role_arn = aws_iam_role.osc-node.arn subnet_ids = aws_subnet.osc[*].id scaling_config { desired_size = 1 max_size = 1 min_size = 1 } depends_on = [ aws_iam_role_policy_attachment.osc-node-AmazonEKSWorkerNodePolicy, aws_iam_role_policy_attachment.osc-node-AmazonEKS_CNI_Policy, aws_iam_role_policy_attachment.osc-node-AmazonEC2ContainerRegistryReadOnly, ] }
outputs.tf: 이 파일에 설정된 값을 통해 EKS 배포완료 후 OutPut 확인하여 정상 배포되었음을 확인 합니다.
locals { config_map_aws_auth = <<CONFIGMAPAWSAUTH apiVersion: v1 kind: ConfigMap metadata: name: aws-auth namespace: kube-system data: mapRoles: | - rolearn: ${aws_iam_role.osc-node.arn} username: system:node:{{EC2PrivateDNSName}} groups: - system:bootstrappers - system:nodes CONFIGMAPAWSAUTH kubeconfig = <<KUBECONFIG apiVersion: v1 clusters: - cluster: server: ${aws_eks_cluster.osc.endpoint} certificate-authority-data: ${aws_eks_cluster.osc.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 }
providers.tf: EKS를 생성할 AWS Key 값이 있습니다.
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" {}
variables.tf: EKS를 생성할 AWS region과 EKS 클러스터 이름 값이 있습니다.
variable "aws_region" { default = "ap-northeast-2" } variable "cluster-name" { default = "terraform-eks-osc" type = string }
vpc.tf: 생성하는 EKS가 사용할 Network 환경을 구축합니다. (VPC, SubNet, Route)
resource "aws_vpc" "osc" { cidr_block = "10.0.0.0/16" tags = tomap({ "Name" = "terraform-eks-osc-node", "kubernetes.io/cluster/${var.cluster-name}" = "shared", }) } resource "aws_subnet" "osc" { 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.osc.id tags = tomap({ "Name" = "terraform-eks-osc-node", "kubernetes.io/cluster/${var.cluster-name}" = "shared", }) } resource "aws_internet_gateway" "osc" { vpc_id = aws_vpc.osc.id tags = { Name = "terraform-eks-osc" } } resource "aws_route_table" "osc" { vpc_id = aws_vpc.osc.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.osc.id } } resource "aws_route_table_association" "osc" { count = 2 subnet_id = aws_subnet.osc.*.id[count.index] route_table_id = aws_route_table.osc.id }
EKS 배포
이제 EKS 배포를 시작합니다.
root@console:~/aws-eks# terraform init Initializing the backend... ... root@console:~/aws-eks# terraform apply ... aws_eks_cluster.osc: Still creating... [10s elapsed] aws_eks_cluster.osc: Still creating... [20s elapsed] aws_eks_cluster.osc: Still creating... [30s elapsed] ... aws_eks_cluster.osc: Creation complete after 10m3s [id=terraform-eks-osc] ... aws_eks_node_group.osc: Creation complete after 1m48s [id=terraform-eks-osc:osc] ╷ │ Warning: Deprecated attribute │ │ on workstation-external-ip.tf line 17, in locals: │ 17: workstation-external-cidr = "${chomp(data.http.workstation-external-ip.body)}/32" │ │ The attribute "body" is deprecated. Refer to the provider documentation for details. ╵ Apply complete! Resources: 18 added, 0 changed, 0 destroyed.
AWS Console에서 EKS 클러스터가 생성 되었음을 다시 한번 확인할 수 있습니다.
EKS Cluster 배포 확인
배포 완료 후 Kubernetes 명령어 사용을 위해 kubectl 명령어를 설치해주고, EKS kubeconfig 파일을 받습니다.
EKS에서는 Control Plane(Master) 노드를 AWS 자체에서 관리하기 때문에, “kubectl get nodes” 명령시, Worker 노드만 확인할 수 있습니다.
root@console:~# curl -o kubectl https://s3.us-west-2.amazonaws.com/amazon-eks/1.23.7/2022-06-29/bin/linux/amd64/kubectl % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 44.4M 100 44.4M 0 0 6061k 0 0:00:07 0:00:07 --:--:-- 7454k root@console:~# chmod +x ./kubectl root@console:~# mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$PATH:$HOME/bin root@console:~# echo 'export PATH=$PATH:$HOME/bin' >> ~/.bashrc root@console:~# kubectl version --short --client Client Version: v1.23.7-eks-4721010 root@console:~# aws configure AWS Access Key ID [None]: AWS_ACCESS_KEY AWS Secret Access Key [None]: AWS_SECRET_KEY Default region name [None]: ap-northeast-2 Default output format [None]: json root@console:~# aws eks update-kubeconfig --region ap-northeast-2 --name terraform-eks-osc Added new context arn:aws:eks:ap-northeast-2:144229005818:cluster/terraform-eks-osc to /root/.kube/config root@console:~# kubectl get nodes NAME STATUS ROLES AGE VERSION ip-10-0-0-156.ap-northeast-2.compute.internal Ready <none> 7m5s v1.23.9-eks-ba74326
AWS에서 EC2가 하나 생성된 것을 확인할 수 있습니다.
AWS ALB Ingress 배포 준비
EKS Ingress를 생성할 때 애플리케이션 트래픽을 로드밸런싱하는 ALB(Application LoadBalancer)가 프로비저닝 됩니다.
ALB 사용을 위해 ALB Ingress Controller를 구성하도록 하겠습니다.
IAM OIDC 자격증명 공급자 생성
(https://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/id_roles_providers_create_oidc.html)
EKS의 Service Account에 IAM Role을 적용하기 위해 IAM OIDC 자격증명 공급자를 생성합니다.
그리고 IAM Role을 만들어 줍니다. Role 이름은 AWSLoadBalancerControllerIAMPolicy 이며, 이 Role은 AWS 로드 밸런서 컨트롤러가 사용자를 대신하여 AWS API를 호출할 수 있도록 허용합니다
Arn 값은 아래 Service Account 만드는 부분에서 사용해야하니 메모해두도록 합니다.
root@console:~# eksctl utils associate-iam-oidc-provider --region ap-northeast-2 --cluster terraform-eks-osc --approve 2022-10-10 04:39:17 [ℹ] will create IAM Open ID Connect provider for cluster "terraform-eks-osc" in "ap-northeast-2" 2022-10-10 04:39:18 [✔] created IAM Open ID Connect provider for cluster "terraform-eks-osc" in "ap-northeast-2" root@console:~# curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 7617 100 7617 0 0 23803 0 --:--:-- --:--:-- --:--:-- 23803 # IAM Role Create root@console:~# aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam-policy.json { "Policy": { "PolicyName": "AWSLoadBalancerControllerIAMPolicy", "PolicyId": "ANPASDFFX7H5BCOTK4Y7E", "Arn": "arn:aws:iam::[AWS_ACCOUNT_ID]:policy/AWSLoadBalancerControllerIAMPolicy", "Path": "/", "DefaultVersionId": "v1", "AttachmentCount": 0, "PermissionsBoundaryUsageCount": 0, "IsAttachable": true, "CreateDate": "2022-10-10T04:40:54+00:00", "UpdateDate": "2022-10-10T04:40:54+00:00" } }
위에서 생성한 IAM Role을 기반으로 Service Account를 생성해주고, EKS 클러스터 내의 TLS 인증서를 자동으로 프로비저닝 하기 위해 Cert-Manager를 배포합니다.
root@console:~# eksctl create iamserviceaccount --cluster=terraform-eks-osc --namespace=kube-system --name=aws-load-balancer-controller --attach-policy-arn=arn:aws:iam::[AWS_ACCOUNT_ID]:policy/AWSLoadBalancerControllerIAMPolicy --override-existing-serviceaccounts --approve 2022-10-10 04:43:33 [ℹ] 1 iamserviceaccount (kube-system/aws-load-balancer-controller) was included (based on the include/exclude rules) 2022-10-10 04:43:33 [!] metadata of serviceaccounts that exist in Kubernetes will be updated, as --override-existing-serviceaccounts was set 2022-10-10 04:43:33 [ℹ] 1 task: { 2 sequential sub-tasks: { create IAM role for serviceaccount "kube-system/aws-load-balancer-controller", create serviceaccount "kube-system/aws-load-balancer-controller", } }2022-10-10 04:43:33 [ℹ] building iamserviceaccount stack "eksctl-terraform-eks-osc-addon-iamserviceaccount-kube-system-aws-load-balancer-controller" 2022-10-10 04:43:34 [ℹ] deploying stack "eksctl-terraform-eks-osc-addon-iamserviceaccount-kube-system-aws-load-balancer-controller" 2022-10-10 04:43:34 [ℹ] waiting for CloudFormation stack "eksctl-terraform-eks-osc-addon-iamserviceaccount-kube-system-aws-load-balancer-controller" 2022-10-10 04:44:04 [ℹ] waiting for CloudFormation stack "eksctl-terraform-eks-osc-addon-iamserviceaccount-kube-system-aws-load-balancer-controller" 2022-10-10 04:44:59 [ℹ] waiting for CloudFormation stack "eksctl-terraform-eks-osc-addon-iamserviceaccount-kube-system-aws-load-balancer-controller" 2022-10-10 04:44:59 [ℹ] created serviceaccount "kube-system/aws-load-balancer-controller" # Cert-Manager 배포 root@console:~# kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.9.1/cert-manager.yaml
VPC SubNet Tag
ALB(Application Load Balancer) 리소스가 생성될 때 AWS 로드 밸런서 컨트롤러가 서브넷을 자동으로 검색할수 있도록 Amazon EKS 클러스터에서 Amazon VPC 서브넷에 태깅합니다.
EKS 클러스터에서 Ingress를 생성할때 권한오류를 방지하기 위해 IAM 의 EKS 클러스터 역할과 EKS 노드역할에 AdministratorAccess Policy를 추가합니다.
Note. 위에서 언급했던 것 처럼 실 운영을 필요로하는 기업이나, 고객사들에서는 AdministratorAccess 권한을 부여해주지 않습니다.
AWS ALB Ingress Controller 배포
ALB Ingress Controller를 배포 하겠습니다.
Yaml 파일 내의 클러스터 이름 수정 후 배포합니다.
root@console:~# curl -Lo ingress-controller.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.4.4/v2_4_4_full.yaml % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 100 31860 100 31860 0 0 42765 0 --:--:-- --:--:-- --:--:-- 42765 root@console:~# cp ingress-controller.yaml ingress-controller.bak root@console:~# diff -u ingress-controller.bak ingress-controller.yaml --- ingress-controller.bak 2022-10-10 04:56:23.156934608 +0000 +++ ingress-controller.yaml 2022-10-10 04:56:42.652878360 +0000 @@ -728,7 +728,7 @@ spec: containers: - args: - - --cluster-name=your-cluster-name + - --cluster-name=terraform-eks-osc - --ingress-class=alb image: amazon/aws-alb-ingress-controller:v2.4.4 root@console:~# kubectl apply -f ingress-controller.yaml customresourcedefinition.apiextensions.k8s.io/ingressclassparams.elbv2.k8s.aws created customresourcedefinition.apiextensions.k8s.io/targetgroupbindings.elbv2.k8s.aws created role.rbac.authorization.k8s.io/aws-load-balancer-controller-leader-election-role created clusterrole.rbac.authorization.k8s.io/aws-load-balancer-controller-role created rolebinding.rbac.authorization.k8s.io/aws-load-balancer-controller-leader-election-rolebinding created clusterrolebinding.rbac.authorization.k8s.io/aws-load-balancer-controller-rolebinding created service/aws-load-balancer-webhook-service created deployment.apps/aws-load-balancer-controller created certificate.cert-manager.io/aws-load-balancer-serving-cert created issuer.cert-manager.io/aws-load-balancer-selfsigned-issuer created mutatingwebhookconfiguration.admissionregistration.k8s.io/aws-load-balancer-webhook created validatingwebhookconfiguration.admissionregistration.k8s.io/aws-load-balancer-webhook created ingressclass.networking.k8s.io/alb created
AWS ALB Ingress Controller 배포 확인
배포 상태를 확인합니다.
root@console:~# kubectl get all -n kube-system NAME READY STATUS RESTARTS AGE pod/aws-load-balancer-controller-5d8dcf49c-sr4v8 1/1 Running 0 26s pod/aws-node-rhb58 1/1 Running 0 32m pod/coredns-d596d9655-484lf 1/1 Running 0 37m pod/coredns-d596d9655-vcjzp 1/1 Running 0 37m pod/kube-proxy-nlwb9 1/1 Running 0 32m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/aws-load-balancer-webhook-service ClusterIP 172.20.144.11 <none> 443/TCP 26s service/kube-dns ClusterIP 172.20.0.10 <none> 53/UDP,53/TCP 37m NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE daemonset.apps/aws-node 1 1 1 1 1 <none> 37m daemonset.apps/kube-proxy 1 1 1 1 1 <none> 37m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/aws-load-balancer-controller 1/1 1 1 26s deployment.apps/coredns 2/2 2 2 37m NAME DESIRED CURRENT READY AGE replicaset.apps/aws-load-balancer-controller-5d8dcf49c 1 1 1 26s replicaset.apps/coredns-d596d9655 2 2 2 37m
배포한 Ingress를 사용하기 위해 WEB 서비스를 하나 배포해보겠습니다.
Python Flask를 통해 Docker Image를 먼저 Build 하겠습니다.
root@console:~# cat osc.py from flask import Flask app = Flask(__name__) @app.route('/osc') def hello_world(): return 'OpenSourceConsulting!' if __name__ == '__main__': app.run(host="0.0.0.0") root@console:~# cat Dockerfile FROM python:3.8 RUN pip install flask RUN pip install httplib2 RUN pip install requests WORKDIR /root/osc ADD osc.py . CMD ["python3", "-u", "osc.py"] root@console:~# docker build -t osc:1.0 .
root@console:~# cat flask-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: osc-webserver labels: app: osc spec: replicas: 1 selector: matchLabels: app: osc template: metadata: labels: app: osc spec: containers: - name: osc-webserver image: osc:1.0 imagePullPolicy: Always ports: - containerPort: 5000 name: flask --- apiVersion: v1 kind: Service metadata: name: osc-webserver-service spec: type: NodePort selector: app: osc ports: - port: 5000 targetPort: 5000 root@console:~# kubectl apply -f flask-deployment.yaml deployment.apps/osc-webserver created service/osc-webserver-service created root@console:~# cat flask-ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: osc-ingress annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: instance spec: rules: - http: paths: - path: /osc pathType: Prefix backend: service: name: osc-webserver-service port: number: 5000 root@console:~# kubectl apply -f flask-ingress.yaml ingress.networking.k8s.io/osc-ingress created root@console:~# kubectl get pod,svc,ing NAME READY STATUS RESTARTS AGE pod/osc-webserver-6cdc5cfd77-27rjc 1/1 Running 0 7m45s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 172.20.0.1 <none> 443/TCP 47m service/osc-webserver-service NodePort 172.20.204.46 <none> 5000:31359/TCP 7m45s NAME CLASS HOSTS ADDRESS PORTS AGE ingress.networking.k8s.io/osc-ingress <none> * k8s-default-oscingre-f4ce67a57c-571439759.ap-northeast-2.elb.amazonaws.com 80 5m56s
Ingress 정책이 정상적으로 만들어 졌고, AWS console에서도 내용을 확인할 수 있습니다.
서비스가 정상적으로 호출되는 것을 확인할 수 있습니다.
AWS EKS Cluster 삭제
terraform destroy 명령으로 구성한 EKS를 지울 수 있습니다.
root@console:~/aws-eks# terraform destroy ... Destroy complete! Resources: 18 destroyed.
마치며.
여기까지 AWS에 EKS 클러스터 구축 및 간단한 WEB 서비스 배포까지 진행해보았습니다.
AWS에 EKS 클러스터 배포방식은 앞서 말씀드린 바와 같이, EC2 방식과 Fargate를 이용한 방식이 있는데요.
Fargate를 이용하면, Pod당 1개의 EC2가 배포되며, 사용하는 리소스만큼의 비용에 대해서만 지불하면되고 인프라적 측면의 관리가 별도로 필요하지 않다는 장점이 있습니다.
하지만 Fargate에서는 DaemonSet 방식의 배포가 불가능하며, Privileged Container를 지원하지 않기 때문에 GPU Pods 사용에 제한적일 수 있습니다. 또한 Resource가 제한적이기 때문에 AWS에서 지원하는 구성을 사용할 수 밖에 없습니다.
인프라의 관리가 필요없이 어플리케이션에 집중을 위해서는 Fargate가 더 나은 선택일 수도 있겠네요.
선택은 사용자의 몫입니다. 🙂
다음에는 AWS EKS Cluster에 ECR(Elastic Container Registry)을 이용한 CI/CD 구축 내용을 포스팅 해보도록 할께요!
참고URL
* https://flask-docs-kr.readthedocs.io/ko/latest/quickstart.html * https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/getting-started.html * https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/alb-ingress.html * https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/aws-load-balancer-controller.html * https://aws.amazon.com/ko/fargate/faqs/
* https://aws.amazon.com/ko/fargate/pricing/?nc=sn&loc=2