EKS 구축 테라폼 코드 설명
코드 구성
eks-terraform-final
├── providers.tf
├── outputs.tf
├── variables.tf
├── workstation-external-ip.tf
├── eks-cluster.tf
├── eks-worker-nodes.tf
├── vpc.tf
└── script
├── ingrass
│ ├── iam_policy.json
│ ├── v2_5_4_full.yaml
│ └── v2_5_4_ingclass.yaml
├── service
│ ├── flask-deployment.yaml
│ ├── flask-ingress.yaml
└── └── flask-service.yaml
providers.tf
- providers.tf 전체 코드
더보기
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0
terraform {
required_version = ">= 0.12"
}
provider "aws" {
region = var.aws_region
}
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" {}
terraform
: Terraform 설정 블록으로, Terraform 자체에 대한 구성을 지정- 최소한 Terraform 버전 0.12 요구
provider "aws"
: AWS 프로바이더를 정의.- variables.tf에서 정의된
var.aws_region
으로 지역을 설정
- variables.tf에서 정의된
data "aws_availability_zones" "available" {}
: AWS의 사용 가능한 가용 영역을 가져오기 위한 데이터 소스를 정의- AWS에서 제공하는 데이터 소스로, 가용 영역 정보를 조회하여 사용할 수 있다.
provider "http" {}
: HTTP 프로바이더를 정의.- workstation-external-ip.tf를 사용하여 외부 IP를 확인하고 EC2 보안 그룹에 대한 액세스를 열 때 사용.
outputs.tf
- outputs.tf 전체 코드
더보기
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0
#
# Outputs
#
locals {
config_map_aws_auth = <<CONFIGMAPAWSAUTH
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: ${aws_iam_role.demo-node.arn}
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
CONFIGMAPAWSAUTH
kubeconfig = <<KUBECONFIG
apiVersion: v1
clusters:
- cluster:
server: ${aws_eks_cluster.demo.endpoint}
certificate-authority-data: ${aws_eks_cluster.demo.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
}
Terraform의 출력(Output)을 정의하는 부분으로, Terraform이 실행된 후 생성된 값들을 사용자에게 보고하는 역할을 한다.
terraform이 실행된후 위에 정의된 값들이 출력된다.
variables.tf
- variables.tf 전체코드
더보기
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0
variable "aws_region" {
default = "us-east-2"
}
variable "cluster_name" {
default = "eks-JaeHyuk"
type = string
}
Terraform 변수를 정의하는 부분으로, 사용자가 구성 파일에서 지정할 수 있다.
var.aws_region
var.cluster_name
으로 default 값을 사용할 수 있다.
workstation-external-ip.tf
- workstation-external-ip.tf 전체 코드
더보기
data "http" "workstation-external-ip" {
url = "http://ipv4.icanhazip.com"
}
# Override with variable or hardcoded value if necessary
locals {
workstation-external-cidr = "${chomp(data.http.workstation-external-ip.response_body)}/32"
}
"http://ipv4.icanhazip.com을 통해 외부 ip를 알아낼 수 있다.
locals.workstation-external-cidr 로 사용될 수 있으며 이는 vpc 설정에 이용된다.
eks-cluster.tf
- eks-cluster.tf 전체 코드
더보기
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0
#
# EKS Cluster Resources
# * IAM Role to allow EKS service to manage other AWS services
# * EC2 Security Group to allow networking traffic with EKS cluster
# * EKS Cluster
#
resource "aws_iam_role" "demo-cluster" {
name = "terraform-eks-demo-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" "demo-cluster-AmazonEKSClusterPolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
role = aws_iam_role.demo-cluster.name
}
resource "aws_iam_role_policy_attachment" "demo-cluster-AmazonEKSVPCResourceController" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSVPCResourceController"
role = aws_iam_role.demo-cluster.name
}
resource "aws_iam_role_policy_attachment" "demo-cluster-AdministratorAccess" {
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess" # AdministratorAccess 정책 추가
role = aws_iam_role.demo-cluster.name
}
resource "aws_security_group" "demo-cluster" {
name = "terraform-eks-demo-cluster"
description = "Cluster communication with worker nodes"
vpc_id = aws_vpc.demo.id
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "terraform-eks-demo"
}
}
resource "aws_security_group_rule" "demo-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.demo-cluster.id
to_port = 443
type = "ingress"
}
resource "aws_eks_cluster" "demo" {
name = var.cluster_name
role_arn = aws_iam_role.demo-cluster.arn
vpc_config {
security_group_ids = [aws_security_group.demo-cluster.id]
subnet_ids = aws_subnet.demo[*].id
}
depends_on = [
aws_iam_role_policy_attachment.demo-cluster-AmazonEKSClusterPolicy,
aws_iam_role_policy_attachment.demo-cluster-AmazonEKSVPCResourceController,
aws_iam_role_policy_attachment.demo-cluster-AdministratorAccess,
]
}
클러스터 IAM 역할 생성
Amazon EKS 서비스가 다른 AWS 서비스를 관리할 수 있도록 하는 IAM 역할을 생성
"Effect": "Allow"
: 이 정책 스타먼트는 허용(Allow)을 의미."Principal"
: AssumeRole을 통해 맡을 수 있는 역할을 지정 여기서는"Service": "eks.amazonaws.com"
으로 설정하여 EKS 서비스가 이 역할을 맡을 수 있도록 한다."Action": "sts:AssumeRole"
: 이 역할을 맡을 때 수행할 수 있는 액션을 지정. 여기서는 다른 역할을 맡을 수 있는 권한을 갖도록 한다.
IAM 역할에 정책을 연결
앞서 생성한 IAM 역할에 정책을 연결
VPC (Virtual Private Cloud) 보안 그룹을 생성
- EKS 클러스터와 워커 노드 간의 통신을 관리하는 VPC 보안 그룹을 생성.
egress
설정은 모든 트래픽을 허용.
보안 그룹 규칙을 생성
클러스터 API 서버와 워크스테이션 간의 통신을 허용하는 보안 그룹 규칙을 생성
cidr_blocks
: 보안 그룹 규칙을 적용할 IP 대역을 지정.- workstation-external-ip.tf 파일에서 정의 된
local.workstation-external-cidr
에 의해 워크스테이션의 외부 IP 대역으로 설정되어 있다.
- workstation-external-ip.tf 파일에서 정의 된
description
: 보안 그룹 규칙에 대한 설명을 지정from_port
,to_port
: 허용할 포트 범위를 지정하여 443 포트만을 대상으로 하고 있다.protocol
: 규칙이 적용되는 프로토콜을 지정.security_group_id
: 보안 그룹 규칙이 적용될 보안 그룹의 ID를 지정type
: 규칙의 유형을 지정- "ingress" : 워크스테이션에서 클러스터로 들어오는 트래픽을 허용하는 규칙.
Amazon EKS 클러스터를 생성
name = var.cluster_name
: 클러스터의 이름을 지정하는 속성.- 이 값은 variables.tf 파일에 의해 변수가 지정되어 있다.
role_arn = aws_iam_role.demo-cluster.arn
: 클러스터를 관리하는 데 사용될 IAM 역할의 Amazon 리소스 이름(ARN)을 지정- 앞서 정의한 IAM 역할인
aws_iam_role.demo-cluster
의 ARN이 여기에 사용.
- 앞서 정의한 IAM 역할인
vpc_config
: VPC 구성에 대한 설정 블록.security_group_ids = [aws_security_group.demo-cluster.id]
: 클러스터에서 사용할 보안 그룹의 ID를 지정.- 이 보안 그룹은 클러스터와 워커 노드 간의 통신을 관리.
subnet_ids = aws_subnet.demo[*].id
: 클러스터에서 사용할 서브넷의 ID를 지정.- 여러 서브넷을 사용하여 다양한 가용 영역에 분산된 워커 노드를 배치할 수 있다.
depends_on
: 클러스터의 IAM 역할과 연결된 정책들이 모두 적용된 후에 클러스터를 생성하도록 의존성을 설정
eks-worker-nodes.tf
- eks-worker-nodes.tf 전체코드
더보기
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0
#
# EKS Worker Nodes Resources
# * IAM role allowing Kubernetes actions to access other AWS services
# * EKS Node Group to launch worker nodes
#
resource "aws_iam_role" "demo-node" {
name = "terraform-eks-demo-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" "demo-node-AmazonEKSWorkerNodePolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
role = aws_iam_role.demo-node.name
}
resource "aws_iam_role_policy_attachment" "demo-node-AmazonEKS_CNI_Policy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
role = aws_iam_role.demo-node.name
}
resource "aws_iam_role_policy_attachment" "demo-node-AmazonEC2ContainerRegistryReadOnly" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
role = aws_iam_role.demo-node.name
}
resource "aws_iam_role_policy_attachment" "demo-node-AdministratorAccess" {
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess" # AdministratorAccess 정책 추가
role = aws_iam_role.demo-node.name
}
resource "aws_eks_node_group" "demo" {
cluster_name = aws_eks_cluster.demo.name
node_group_name = "JaeHyuk-node-group"
node_role_arn = aws_iam_role.demo-node.arn
subnet_ids = aws_subnet.demo[*].id
instance_types = [ "t3.xlarge" ]
scaling_config {
desired_size = 4
max_size = 5
min_size = 1
}
depends_on = [
aws_iam_role_policy_attachment.demo-node-AmazonEKSWorkerNodePolicy,
aws_iam_role_policy_attachment.demo-node-AmazonEKS_CNI_Policy,
aws_iam_role_policy_attachment.demo-node-AmazonEC2ContainerRegistryReadOnly,
aws_iam_role_policy_attachment.demo-node-AdministratorAccess,
]
}
노드 IAM 역할 생성
- 노드 그룹을 위한 IAM 역할을 정의
"Action": "sts:AssumeRole"
: 이 역할을 맡을 때 수행할 수 있는 액션을 지정. 여기서는 다른 역할을 맡을 수 있는 권한을 갖도록 한다.
IAM 역할에 정책을 연결
AmazonEKSWorkerNodePolicy
는 노드가 EKS 클러스터에 가입할 수 있도록 허용하는 권한을 제공
Amazon EKS 노드 그룹을 정의
cluster_name
: 노드 그룹이 속할 EKS 클러스터의 이름을 지정.node_group_name
: 노드 그룹의 이름을 지정.node_role_arn
: 노드 그룹이 사용할 IAM 역할의 Amazon 리소스 이름(ARN)을 지정.subnet_ids
: 노드가 배치될 서브넷의 ID를 지정.- vpc.tf의 설정을 참고 한다.
instance_types
: 노드 인스턴스의 유형을 지정.
💡 "t3.xlarge” 는 유로 인스턴스 유형임으로 과금에 주의해야한다.
scaling_config
: 노드 그룹의 자동 크기 조정 구성을 지정.depends_on
: 클러스터의 IAM 역할과 연결된 정책들이 모두 적용된 후에 클러스터를 생성하도록 의존성을 설정
vpc.tf
- vpc.tf 전체 코드
더보기
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0
#
# VPC Resources
# * VPC
# * Subnets
# * Internet Gateway
# * Route Table
#
resource "aws_vpc" "demo" {
cidr_block = "10.0.0.0/16"
tags = tomap({
"Name" = "terraform-eks-demo-node",
"kubernetes.io/cluster/${var.cluster_name}" = "shared",
"kubernetes.io/role/elb" = "1"
})
}
resource "aws_subnet" "demo" {
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.demo.id
tags = tomap({
"Name" = "terraform-eks-demo-node",
"kubernetes.io/cluster/${var.cluster_name}" = "shared",
"kubernetes.io/role/elb" = "1"
})
}
resource "aws_internet_gateway" "demo" {
vpc_id = aws_vpc.demo.id
tags = {
Name = "terraform-eks-demo"
}
}
resource "aws_route_table" "demo" {
vpc_id = aws_vpc.demo.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.demo.id
}
}
resource "aws_route_table_association" "demo" {
count = 2
subnet_id = aws_subnet.demo[count.index].id
route_table_id = aws_route_table.demo.id
}
AWS VPC를 정의
cidr_block
은 VPC의 IP 주소 범위를 나타낸다.- 여러 태그를 정의하여 리소스에 메타데이터를 추가합니다.
AWS 서브넷을 정의
count
: 서브넷의 수를 지정 → 2 : 두 개의 서브넷을 생성- 각 서브넷은 특정 가용 영역에 배치.
cidr_block
: 각 서브넷의 IP 주소 범위를 나타낸다.map_public_ip_on_launch
: 서브넷으로 시작된 인스턴스에 퍼블릭 IP 주소가 할당되어야 함을 나타내려면 true를 지정 (Default isfalse
)vpc_id
: 클러스터와 연결된 vpc의 id( = The ID of the subnet)
AWS 인터넷 게이트웨이를 정의
VPC에 연결되어 인터넷과의 통신을 제공
AWS 라우트 테이블을 정의
aws_route_table
: AWS 라우트 테이블을 정의.- 0.0.0.0/0 : 모든 트래픽을 인터넷 게이트웨이로 보내기 위한 기본 경로가 설정
서브넷과 라우트 테이블 간의 연결을 정의
aws_route_table_association
: 서브넷과 라우트 테이블 간의 연결을 정의- 두 개의 서브넷이 각각의 라우트 테이블과 연결
Trouble Shooting
서브넷 관리 : https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/network_reqs.html
- 서브넷에 로드 밸런서를 배포하려는 경우 다음과같은 서브넷 태그가 있어야한다.
- 프라이빗 서브넷
- kubernetes.io/role/internal-elb 1
- 퍼블릭 서브넷
- kubernetes.io/role/elb 1
- 프라이빗 서브넷
- 버전이 Kubernetes 이하인
1.18
클러스터가 생성되면 Amazon EKS에서 지정된 모든 서브넷에 다음 태그를 추가했어야했다.- kubernetes.io/cluster/
my-cluster
shared
- kubernetes.io/cluster/
'DevOps' 카테고리의 다른 글
Jenkins + gitops (0) | 2023.12.18 |
---|---|
CI / CD 란? (0) | 2023.12.18 |
EKS에서 기존 서비스에 DB(mysql) 연결 방법(pod 간 통신) (0) | 2023.12.18 |
Terraform을 이용한 EKS 클러스터 생성 및 서비스 배포 (0) | 2023.12.18 |
쿠버네티스(K8) , EKS란? (1) | 2023.12.17 |