
EFK는 Amazon Kubernetes Service인 EKS에 구축하였다. EKS 클러스터는 아래의 Terraform 을 사용하여 프로비저닝한다.
다행히 나는 AWS에 여분의 크레딧이 남아있어서 비용부담이 안되지만 쌩돈나가게 생겼다면 그냥 GCP 신규가입하면 300달러 주니까 그걸로 하는것도 나쁘지 않은 방법이다.
비용 절감을 위해 EKS클러스터를 구성할 수 있는 최소유형 (t3.medium)으로 생성한다.

* 온디멘드로 시간당 0.052달러 우리나라 돈으로 57원이고 스팟 인스턴스는 0.014달러 우리나라 돈으로 는 약 15원이다.
> provider.tf
provider "aws" {
region = "ap-northeast-2"
}
> backend.tf
terraform {
backend "s3" {
bucket = "seunghyeon-saving-remote-state"
key = "eks/terraform.tfstate"
region = "ap-northeast-2"
encrypt = true
}
}
> main.tf
############ Local Variable ######################
# 로컬변수입니다. 클러스터의 이름과 배스천 호스트에 접속가능한 IP대역을 설정해주세요.
locals {
cluster_name = "seunghyeon-eks"
region = "ap-northeast-2"
bastion-con-ip = ["0.0.0.0/0"]
}
################### Create VPC ###################
module "vpc" {
source = "git::https://github.com/SeungHyeonShin/terraform.git//modules/eks-vpc?ref=v1.3.0"
aws_vpc_cidr = "192.168.0.0/16"
aws_private_subnets = ["192.168.1.0/24", "192.168.2.0/24"]
aws_public_subnets = ["192.168.11.0/24", "192.168.12.0/24"]
aws_region = local.region
aws_azs = ["ap-northeast-2a", "ap-northeast-2c"]
aws_default_name = "seunghyeon"
global_tags = {
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
}
}
################### Create EKS ###################
# EKS 클러스터를 프로비저닝합니다.
# 비용절감을 위해 On-Demand 노드 하나, Spot-Instance 노드 하나로 구성합니다.
module "eks" {
source = "git::https://github.com/terraform-aws-modules/terraform-aws-eks.git?ref=v13.2.1"
cluster_name = local.cluster_name
vpc_id = module.vpc.aws_vpc_id
subnets = module.vpc.private_subnets
cluster_version = "1.18"
manage_aws_auth = false
# EKS Cluster의 보안그룹을 추가시킴
worker_security_group_id = module.eks.cluster_security_group_id
# This is Important to Use K8S Objects Module's config_path
write_kubeconfig = true
config_output_path = pathexpand("~/.kube/kubeconfig_${local.cluster_name}")
node_groups = [
{
name = "on-demand-1"
instance_type = "t3.medium"
asg_max_size = 3
key_name = aws_key_pair.shin-eks.key_name
kubelet_extra_args = "--node-labels=spot=false"
suspended_processes = ["AZRebalance"]
additional_tags = {
"k8s.io/cluster-autoscaler/enabled" = "true"
}
source_security_group_ids = [
aws_security_group.seunghyeon-bastion-sg.id
]
}
]
worker_groups_launch_template = [
{
name = "spot-1"
override_instance_types = ["t3.medium", "t3a.medium"]
spot_instance_pools = 5
asg_max_size = 5
asg_desired_capacity = 1
key_name = aws_key_pair.shin-eks.key_name
kubelet_extra_args = "--node-labels=node.kubernetes.io/lifecycle=spot"
# EKS Cluster의 보안그룹을 추가시킴
additional_security_group_ids = [module.eks.cluster_primary_security_group_id]
additional_tags = {
"k8s.io/cluster-autoscaler/enabled" = "true"
}
source_security_group_ids = [
aws_security_group.seunghyeon-bastion-sg.id
]
}
]
}
############ Upload Key Pair ##############
resource "aws_key_pair" "shin-eks" {
key_name = "shin-eks"
public_key = file("~/.ssh/project/shin-eks.pub")
}
resource "aws_key_pair" "shin-eks-bastion" {
key_name = "shin-eks-bastion"
public_key = file("~/.ssh/project/shin-eks-bastion.pub")
}
############ Create Bastion Host ################
resource "aws_security_group" "seunghyeon-bastion-sg" {
name = "seunghyeon-bastion"
vpc_id = module.vpc.aws_vpc_id
ingress {
from_port = 22
protocol = "tcp"
to_port = 22
cidr_blocks = local.bastion-con-ip
}
egress {
from_port = 0
protocol = "-1"
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
"Name" = "seunghyeon-EKS-bastion-sg"
}
}
resource "aws_instance" "bastion" {
ami = "ami-027ce4ce0590e3c98"
instance_type = "t2.micro"
subnet_id = element(module.vpc.public_subnets, 0)
key_name = aws_key_pair.shin-eks-bastion.key_name
vpc_security_group_ids = [
aws_security_group.seunghyeon-bastion-sg.id
]
tags = {
"Name" = "seunghyeon-EKS-bastionHost"
}
}
terraform apply로 프로비저닝을 시작하면 약 15~20분 사이로 EKS클러스터 구성이 완료된다. EKS 클러스터 생성이 완료되었으면 클러스터를 핸들링 하기위해 kubeconfig 파일을 환경변수로 지정해주자.
EKS 클러스터가 생성되면 kubeconfig 파일은 $HOME/.kube/kubeconfig_seunghyeon-eks-cluster 로 저장이 된다.
해당 kubeconfig파일의 이름을 config로 변경해주거나 KUBECONFIG 환경변수에 경로를 지정해줘야한다.
# Kubeconfig 파일의 경로를 지정해줌 (택 1)
export KUBECONFIG=$HOME/.kube/kubeconfig_seunghyeon-eks-cluster
# Kubeconfig 파일의 이름을 변경
mv $HOME/.kube/kubeconfig_seunghyeon-eks-cluster $HOME/.kube/config
kubeconfig파일을 지정해주고 나면 EKS클러스터를 컨트롤 할 수 있게 된다.
> k get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ip-192-168-1-151.ap-northeast-2.compute.internal Ready <none> 54m v1.18.9-eks-d1db3c 192.168.1.151 <none> Amazon Linux 2 4.14.209-160.335.amzn2.x86_64 docker://19.3.6
ip-192-168-1-25.ap-northeast-2.compute.internal Ready <none> 54m v1.18.9-eks-d1db3c 192.168.1.25 <none> Amazon Linux 2 4.14.209-160.335.amzn2.x86_64 docker://19.3.6
Spot-Instance의 보안그룹에 설정되어 있는 태그인 kubernetes.io/cluster/seunghyeon-eks를 삭제해야 한다. 원래 해당 태그는 클러스터의 보안그룹에만 설정이 되어있는데 Terraform 코드에서 Spot-Instance로 EKS를 구성하기 위하여 보안그룹을 하나 더 생성을 해놓은 것이다.
EKS에서는 로드밸런서를 프로비저닝 시 설정되어있는 Tag 기반으로 보안그룹의 Inbound에 해당 로드밸런서의 보안그룹을 허용하게 되는데 만약, 삭제를 안한다면 kubernetes.io/cluster/seunghyeon-eks Tag가 중복이 되면 어느 보안그룹에 추가를 해야할지 못찾게 되어서 로드밸런서가 생성이 안된다.


EFK스택을 배포할 인프라 설정은 끝났다.
이제 남은것은 Elasticsearch, Fluentd, Kibana를 배포하고 설정하면 된다.