EKS IaC
April 2024 (898 Words, 5 Minutes)
EKS IaC
Infrastructure as Code 의 줄인말로, 구성할 인프라를 코드로 선언하는 방식입니다.
Hashicorp 사에서 공개한 도구인 Terraform 을 이용하여 AWS 자원을 프로비저닝 해볼 생각입니다.
실습은 Mac 에서 진행하기위해 brew로 설치를 진행합니다
# tfenv 설치
brew install tfenv
# 설치 가능 버전 리스트 확인
tfenv list-remote
# 테라폼 1.5.1 버전 설치
tfenv install 1.8.1
# 테라폼 1.5.1 버전 사용 설정
tfenv use 1.8.1
# tfenv로 설치한 버전 확인
tfenv list
# 테라폼 버전 정보 확인
terraform version
# 자동완성
terraform -install-autocomplete
## 참고 .zshrc 에 아래 추가됨
cat ~/.zshrc
autoload -U +X bashcompinit && bashcompinit
complete -o nospace -C /usr/local/bin/terraform terraform
# AWS CLI 설치
brew install awscli
# EKSCTL 설치
brew install eksctl
# Kubectl 설치
brew install kubernetes-cli
# Helm 설치
brew install helm
# 추가 도구 설치
brew install tree jq watch
VS Code Extension 설치
Extension → HashiCorp HCL 설치
기본 환경준비
mkdir learn-terraform
cd learn-terraform
touch main.tf
사용하려는 최신 AL2 ami ID 검색
AL2ID=`aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" "Name=state,Values=available" --query 'Images|sort_by(@, &CreationDate)[-1].[ImageId]' --output text`
echo $AL2ID
리소스 생성 Test
cat <<EOT > main.tf
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "example" {
ami = "$AL2ID"
instance_type = "t2.micro"
}
EOT
배포하기
# plan 실행 시 아래와 같은 정보가 출력
terraform plan
# apply 실행
terraform apply
# Enter a value: yes 입력
삭제
# 리소스 삭제
terraform destroy -auto-approve
HCL
HCL(HashiCorp Configuration Language)은 Hashicorp사에서 IaC와 구성 정보를 명시하기 위해 개발된 오픈 소스 도구입니다.
HCL 특징
- IaC는 코드를 통해 인프라를 관리하고 프로비저닝
- HCL이 테라폼에서의 코드영역. 읽기쉽고 빠르게 배울 수 있게 설계
- 선언적(declarative) 특성을 갖고 Turing-complete 언어적 특성
json type으로 생성하는것보다 훨씬 간결하고 읽기 쉽다는 점이 제일 큰 장점입니다.
json type에 비해 약 50~70%정도 짧아진다고 하네요
HCL에서 사용하는 표현식은 다음과 같습니다
// 한줄 주석 방법1
# 한줄 주석 방법2
/*
라인
주석
*/
locals {
key1 = "value1" # = 를 기준으로 키와 값이 구분되며
myStr = "TF ♡ UTF-8" # UTF-8 문자를 지원한다.
multiStr = <<EOF
Multi
Line
String
with anytext
EOF
boolean1 =true # boolean true
boolean2 =false # boolean false를 지원한다.
deciaml = 123 # 기본적으로 숫자는 10진수,
octal = 0123 # 0으로 시작하는 숫자는 8진수,
hexadecimal = "0xD5" # 0x 값을 포함하는 스트링은 16진수,
scientific = 1e10 # 과학표기 법도 지원한다.
# funtion 호출 예
myprojectname = format("%s is myproject name", var.project)
# 3항 연산자 조건문을 지원한다.
credentials = var.credentials == "" ? file(var.credentials_file) : var.credentials
}
테라폼 블록
테라폼 버전이나 프로바이더 버전들은 명시적으로 선언해 실행 오류를 최소화하는것을 목표로 합니다.
멱등성을 보장하기 위해서죠
terraform {
required_version = "~> 1.3.0" # 테라폼 버전
required_providers { # 프로바이더 버전을 나열
random = {
version = ">= 3.0.0, < 3.1.0"
}
aws = {
version = "4.2.0"
}
}
cloud { # Cloud/Enterprise 같은 원격 실행을 위한 정보 [참고: Docs]
organization = "<MY_ORG_NAME>"
workspaces {
name = "my-first-workspace"
}
}
backend "local" { # state를 보관하는 위치를 지정 [참고: Docs, local, remote, s3]
path = "relative/path/to/terraform.tfstate"
}
}
버전 체계는 시맥틴 버전관리를 따라
# version = Major.Minor.Patch
version = 1.3.4
일반적으로 MAJOR.MINOR.PATCH
형태로 표현됩니다.
MAJOR
: 호환되지 않는 API 변경MINOR
: 기존 버전과 호환되는 새로운 기능 추가PATCH
: 기존 버전과 호환되는 버그 수정
테라폼에서의 버전 제약 구문은 다른 프로그래밍 언어의 종속성 관리와 매우 유사하게 동작합니다. 여기 몇 가지 주요 연산자와 그들이 어떻게 작동하는지에 대한 간단한 요약입니다:
=
또는 없음: 이 연산자는 오직 지정된 버전만을 허용합니다. 다른 조건과는 병합될 수 없습니다.!=
: 이 연산자는 지정된 버전을 제외하고 모든 것을 허용합니다.>, >=, <, <=
: 이 연산자들은 기본 수학적 비교를 수행하여 버전을 허용하거나 제외합니다.~>
: 이 연산자는 “거의 동일한” 버전을 허용합니다. 지정된 버전의 마지막 숫자만이 증가할 수 있습니다. 예를 들어,~> 1.2
는 1.3, 1.4 등을 허용하지만 2.0은 허용하지 않습니다.
리소스 구성
리소스 블록은 Terraform 코드에서 실제 클라우드 리소스를 선언하고 생성합니다.
- 기본 구조:
resource
를 사용하여 리소스 블록을 시작합니다. - 리소스 유형:
resource
프로바이더에 종속적입니다. - 이름: 동일한 유형의 리소스를 구분하기 위해 사용합니다.
- 구성 인수: 중괄호
{}
안에는 해당 리소스의 속성이나 설정을 정의합니다.
코드 예시
resource "local_file" "abc" {
content = "123"
filename = "${path.module}/abc.txt"
}
resource "aws_instance" "web" {
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
}
주의사항
- 프로바이더 블록 별도 선언 권장:
resource
블록에서 사용되는 리소스 유형은 특정 프로바이더에 종속되기 떄문에 별도로 프로바이더를 선언하는 것이 권장됩니다.
종속성
resource, module의 선언으로 프로비저닝 되는 요소의 순서를 정의할수있습니다.
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
resource "local_file" "def" {
content = local_file.abc.content
filename = "${path.module}/def.txt"
}
이런식으로 def는 abc를 참조해야만 생성이 가능하지만, 명시적인 depend_on 파라미터를 사용하여 종속성을 부여할수있스비낟.
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
resource "local_file" "def" {
depends_on = [
local_file.abc
]
content = "456!"
filename = "${path.module}/def.txt"
}
리소스 속성
- 리소스 구성에서 참조 가능한 값은 인수와 속성이다
- 인수 : 리소스 생성 시 사용자가 선언하는 값
- 속성 : 사용자가 설정하는 것은 불가능하지만 리소스 생성 이후 획득 가능한 리소스 고유 값
# Terraform Code
resource "<리소스 유형>" "<이름>" {
<인수> = <값>
}
# 리소스 참조
<리소스 유형>.<이름>.<인수>
<리소스 유형>.<이름>.<속성>
resource "kubernetes_namespace" "example" {
metadata {
annotations = {
name = "example-annotation"
}
name = "terraform-example-namespace"
}
}
resource "kubernetes_secret" "example" {
metadata {
namespace = kubernetes_namespace.example.metadata.0.name # namespace 리소스 인수 참조
name = "terraform-example"
}
data = {
password = "P4ssw0rd"
}
}
쿠버네티스 프로바이더의 Namespace를 리소스로 생성해,
Secret을 해당 Namespace에 생성하는 종속성을 갖는 예시입니다.
Namespace 가 바뀌어도 참조중인 모든 리소스가 업데이트되죠.
데이터 소스 구성
데이터 소스
는 외부 리소스나 저장된 정보를 참조할 때 사용합니다.
데이터 소스를 설정하는 방법은 리소스 블록을 정의하는 것과 비슷합니다.
데이터 소스 유형은 프로바이더 이름과 리소스 유형으로 구성되며, 이후에는 고유한 이름과 구성 인수를 선언합니다.
cat <<'EOT' > main.tf
data "local_file" "abc" {
filename = "${path.module}/abc.txt"
}
EOT
메타인수로는 depends_on
, count
, for_each
, lifecycle
등이 사용 가능합니다.
- depends_on : 종속성을 선언하며, 선언된 구성요소와의 생성 시점에 대해 정의
- count : 선언된 개수에 따라 여러 리소스를 생성
- for_each : map 또는 set 타입의 데이터 배열의 값을 기준으로 여러 리소스를 생성
- lifecycle : 리소스의 수명주기 관리