SlideShare a Scribd company logo
테라폼으로 글로벌 서비스
구성
- DRY 체험기 -
devops@mykoon.com
Spoon Radio Infra Member
● 노가다를 싫어하는 노땅 엔지니어 2명
○ 최상기(Martin): https://www.linkedin.com/in/sanggi-choi/
○ 백영진(Paul): https://www.linkedin.com/in/youngjin-baek-8a2a74a4/
● 묵묵히 열심히 겁나게 달려주는 엔지니어 1명
○ 박민호(Ash): https://www.linkedin.com/in/park-minho-4896b7117/
Agenda
● Spoon Radio 소개
● 요구 사항
● 인프라 구성 도구
● 코드 중복 극복기 (DRY Journey)
○ Phase 1: Terraform
○ Phase 2: Terraform Module
○ Phase 3: Terragrunt
○ 고민
○ 숙제
● 정리
SPOON RADIO
● 개요: 개인 오디오 라이브 스트리밍 모바일 플랫폼
● 특징: 10 ~ 20대를 타겟팅 한 모바일 미디어 채널
● 2016년(한국), 2017년(인도네시아/베트남), 2018년(일본/중동 GCC 5개국)
● 글로벌 다운로드 900만 / 글로벌 MAU 170만
6개월 간의 중복 코드 탈출기(ing)
● WET: Write Everything Twice
○ 중복, 반복된 코드
○ 수정 및 재 활용 하는데 많은 비용 발생
● DRY: Don't Repeat Yourself
○ 품질과 무결성 확보
○ 읽기 쉽고
○ 재활용 가능
○ 수정 및 활용 하는데 비용이 낮음.
요구 사항
● 보통 인프라 구조는 거의 유사하지만, 아주 약간 다른 환경 구성 관리를 해야
함.
○ multiple aws accounts & region , environments,
○ aws resource(IAM, VPC, Subnet, RDS, EC2, Aurora, ALB, Lambda, S3, Route53 and so on.)
=> 5개국 서비스 구성시 15개의 유사 인프라 구성과 관리
● 기존 Legacy Infra를 Code 기반으로 자동화
○ AWS Well-Architected & ISMS & ISO27001 대응 인프라 구성
○ 생산성이 높은 인프라 환경 구성
인프라 구성 도구
Code Repository
Infrastructure
Provisioning
Image
Management
Configuration
Management
CI/CD
Code Repository
(Terraform, Packer,
AWX, Ansible,
Dockerfile..etc)
AWS Infrastructure
(VPC, Subnet,
Security Group,
IAM, S3.. etc)
AWS AMI Base
Image
(Amazon Linux,
Ubuntu,
CentOS..etc)
Software
Provisioning
(Nginx,Python,Java,
Docker..etc)
Continuous
Integration &
Delivery
(Terraform, Packer,
Application, Web)
Terragrunt
Phase 1 - Terraform
● IaC - 인프라 생성, 변경, 설정을 코드 관리
○ 비용의 감소(돈, 인력, 노력 등)
○ 빠른 실행 속도
○ 위험 관리
○ 불확실성에 대한 유연함 - 아는 만큼 보이고, 처음 부터 완벽할 수 없다.
● Terraform
○ Terraform은 HashiCprop에서 만든 오픈 소스 도구이며,
인프라를 코드 형태로 정의하는 간편한 선언형 프로그래밍 언어
■ Multi Provider
■ Large Community
○ 그냥 해 보고 싶었다.
Phase 1 - 시작
● VPC
● Subnet
● Route Table
● IGW
● NAT
Phase 1 - 단순 리소스 나열
# kor/main.tf
provider "aws" {
region = "ap-northeast-2"
access_key ="XXXXXXXXXXXXXXXX"
secert_key ="XXXXXXXXXXXXXXXX"
}
resource "aws_vpc" "test-vpc" {
cidr_block = "10.1.0.0/16"
instance_tenancy = "default"
enable_dns_support = "true"
enable_dns_hostnames = "true"
enable_classiclink = "false"
tags {
Name = "test-vpc"
}
}
resource "aws_subnet" "public-subnet-2a" {
vpc_id =
"${aws_vpc.test-vpc.id}"
cidr_block = "10.1.1.0/24"
map_public_ip_on_launch = "true"
availability_zone = "ap-northeast-2a"
tags {
Name = "public-subnet-2a"
}
}
resource "aws_subnet" "private-subnet-2a" {
vpc_id =
"${aws_vpc.test-vpc.id}"
cidr_block = "10.1.2.0/24"
map_public_ip_on_launch = "false"
availability_zone = "ap-northeast-2a"
tags {
Name = "private-subnet-2a"
}
}
resource "aws_internet_gateway" "gw" {
vpc_id = "${aws_vpc.test-vpc.id}"
tags {
Name = "internet-gateway"
}
}
resource "aws_route_table" "rt1" {
vpc_id = "${aws_vpc.test-vpc.id}"
route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.gw.id}"
}
tags {
Name = "Default"
}
}
resource "aws_route_table_association"
"association-subnet" {
subnet_id = "${aws_subnet.public-1.id}"
route_table_id = "${aws_route_table.rt1.id}"
}
output "vpc-id" {
value = "${aws_vpc.test-vpc.id}"
}
output "vpc-public-subnet-cidr" {
value =
"${aws_subnet.public-subnet-2a.cidr_block}"
}
output "vpc-public-subnet-id" {
value = "${aws_subnet.public-subnet-2a.id}"
}
output "vpc-private-subnet-cidr" {
value =
"${aws_subnet.private-subnet-2a.cidr_block}"
}
output "vpc-private-subnet-id" {
value = "${aws_subnet.private-subnet-2a.id}"
}
Phase 1 - main.tf 중복
KR JP IN VE MENA
+ PRD
- main.tf
+ STG
- main.tf
+ DEV
- main.tf
+ PRD
- main.tf
+ STG
- main.tf
+ DEV
- main.tf
+ PRD
- main.tf
+ STG
- main.tf
+ DEV
- main.tf
+ PRD
- main.tf
+ STG
- main.tf
+ DEV
- main.tf
+ PRD
- main.tf
+ STG
- main.tf
+ DEV
- main.tf
● 5개 국가, 3개의 인프라 환경 => 총 15개의 인프라 환경을 구성 관리해야 함.
○ 국가, 환경은 다르지만 동일한 인프라 구조를 만들기 위한 중복되는 옵션의 resource가 다수
발생.
○ 대략 100 ~ 200 line 수준의 main.tf WET Code 발생.
Phase 1 - 결국
● 단순 리소스 나열만으로는 15벌 인프라 전개 불가능
○ 재활용이 불가능
○ 비슷한 리소스의 대량 중복 발생
○ 유지 보수 불가능
○ 이렇게 할 거면 Hands - On과 차이가....
Phase 2 - Terraform Module
● Data를 변수 처리한 리소스 구성 파일 묶음.
○ 비슷한 리소스를 반복 정의하는 고통에서 벗어날 수 있다.
○ 사용자 정의 모듈 만들어 활용
○ 외부에서 이미 잘 만들어둔 모듈 활용
■ https://registry.terraform.io/
■ https://github.com/cloudposse
■ https://github.com/terraform-aws-modules
○ 리소스에는 versioning이 안되지만, 모듈에는 버저닝 가능
-> 모듈간 독립성 확보(의존성 제거)
Phase 2 - 시도
# terraform-aws-vpc/main.tf
locals {
max_subnet_length = max(
length(var.private_subnets),
length(var.elasticache subnets),
length(var.database_subnets),
length(var.redshift_subnets),
)
nat_gateway_count = var.single_nat_gateway ? 1 :
var.one_nat_gateway_per_az ? length(var.azs) :
local.max_subnet_length
………… 길어요...
# prd-kr/main.tf
terraform {
backend "s3" {
bucket = "backend-bucket"
key = "prd-kr-vpc/terraform.tfstate"
region = "ap-northeast-2"
profile = "prd-kr"
}
}
provider aws {
region = "ap-northeast-2"
profile = "prd"
}
module "network" {
source = "../modules/network"
name = "${var.name}"
cidr = "${var.cidr}"
azs = "${var.azs}"
public_subnets = "${var.public_subnets}"
env = "${var.env}"
}
# prd-kr/vars.tf
variable name {
type = "string"
default = ""
}
variable cidr {
type = "string"
default = "0.0.0.0/0"
}
variable public_subnets {
type = "list"
default = ["0.0.0.0/0"]
}
variable private_subnets {
type = "list"
default = ["0.0.0.0/0"]
}
variable azs {
type = "list"
default = [""]
}
# prd-kr/terraform.tfvars
name = "prd-kor-vpc"
cidr = "10.1.0.0/16"
public_subnets = ["10.1.1.0/24", ...]
public_subnets = ["10.1.2.0/24", ...]
asz = ["ap-northeast-2a", ...]
env = "prd-kor
vars.tf
Duplicated
main.tf
Duplicated
Phase 2 - Repeat Itself, Again
● module을 사용하면서 resource는 재활용이 가능해
졌지만, root module을 참조하는 sub module과 변수
정의 부분은 각 환경별 중복이 발생
● terraform.tfvars을 제외한 곳에서 WET code 발생
# jpn/terraform.tfvars
name = "prd-jpn-vpc"
cidr = "10.2.0.0/16"
public_subnets = ["10.2.0.0/24", ...]
public_subnets = ["10.2.1.0/24", ...]
asz = ["ap-northeast-2a", ...]
env = "prd-kor
# kor/terraform.tfvars
name = "prd-kor-vpc"
cidr = "10.1.0.0/16"
public_subnets = ["10.1.1.0/24", ...]
public_subnets = ["10.1.2.0/24", ...]
asz = ["ap-northeast-2a", ...]
env = "prd-kor
# kor/main.tf
module "network" {
source = "../modules/network"
name = "${var.name}"
cidr = "${var.cidr}"
azs = "${var.azs}"
public_subnets = "${var.public_subnets}"
env = "${var.env}"
}
# kor/vars.tf
variable name {
type = "string"
default = ""
}
variable cidr {
type = "string"
default = "0.0.0.0/0"
}
# jpn/main.tf
module "network" {
source = "../modules/network"
name = "${var.name}"
cidr = "${var.cidr}"
azs = "${var.azs}"
public_subnets = "${var.public_subnets}"
env = "${var.env}"
}
# jpn/vars.tf
variable name {
type = "string"
default = ""
}
variable cidr {
type = "string"
default = "0.0.0.0/0"
}
Phase 2 - 세상에 공짜는 없다.
● multiple env에서 그래도 중복 발생(main.tf, var.tf)
○ 5개 국가, 3개 환경 구성에 대한 중복은 그대로
○ global, local 변수 정의 관리 불편
● 오픈소스 모듈도 결국 내 입맛에 맞게 수정
○ 조금만 바꿔도 삭제 후 재 생성 ㅜㅜ
■ 요구 사항에 맞게 Lifecycle 관리 추가
○ resource 생성을 모듈 하위에서 생성하기에 수정하기가 불가함
○ 결국에 오픈소스 전체 코드 분석 후 수정함
Phase 3 - Terragrunt
● gruntworks.io에서 개발하고, Terraform만으로는 부족한 기능 보완
● 단순한 인프라는 Terraform으로도 충분하다.
그러나 인프라 구성이 커질 수록 모듈간의 연관 관계 및 중복 발생
● Orchestration = Terragrunt
○ 모듈 간의 코드 중복을 최소화
○ 모듈 간의 종속 관계 제거
Gruntwork.io
Terragrunt 기본 구조
● /terraform.tfvars
○ terragrunt의
환경설정
● /globals.tfvars
○ root module
○ root vars
● locals.tfvars
○ sub module
○ sub vars
● terraform.tfvars
○ 각각의 vars
terragrunt = {
….
terraform {
extra_arguments "-var-file" {
commands = ["${get_terraform_commands_that_need_vars()}"]
optional_var_files = [
"${get_tfvars_dir()}/${find_in_parent_folders("globals.tfvars", "ignore")}",
"${get_tfvars_dir()}/${find_in_parent_folders("locals.tfvars", "ignore")}"
]
}
}
}
namespace = "prod"
# dynamodb & s3
bucket = "prod-terraform-state"
config_region = "ap-northeast-2"
dynamodb_table = "prod-terraform-db"
stage = "kor"
aws_region = "ap-northeast-2"
# remote state key
vpc_remote_state_key = "prod/kor/terraform.tfstate"
terragrunt = {
terraform {
source = "git::ssh/spooncast/terraform-service-repo.git?ref=release/v0.0.1//bastion"
}
include = {
path = "${find_in_parent_folders()}"
}
}
name = "bastion"
instance_type = "t2.micro"
cidr_office = "xxx.xxx.xxx.xxx/32"
코드와 데이터의 분리(Data Driven Design)
# prod/main.tf
terraform {
# The configuration for this backend will be filled in by
Terragrunt
backend "s3" {}
}
provider aws {
region = "${var.region}"
profile = "${var.profile}"
}
module "network" {
source = "terraform-aws-modules/vpc/aws"
name = "${var.name}"
cidr = "${var.cidr}"
azs = "${var.azs}"
public_subnets = "${var.public_subnets}"
env = "${var.country}"
}
# global.tfvars
profile = "prod"
# prod/local.tfvars
region = "ap-northeast-2"
country = "kr"
# prod/terraform.tfvars
terragrunt = {
terraform {
source = "network"
}
include = {
path = "${find_in_parent_folders()}"
}
}
name = "vpc-prd-kor"
cidr = "10.1.0.0/16"
azs = ["ap-northeast-2a", "ap-northeast-2b",
"ap-northeast-2c"]
public_subnets = ["10.1.1.0/24", "10.1.2.0/24,
"10.1.3.0/24]
# prod/local.tfvars
region = "ap-northeast-1"
country = "jp"
# prod/terraform.tfvars
terragrunt = {
terraform {
source = "network"
}
include = {
path = "${find_in_parent_folders()}"
}
}
name = "vpc-prd-jp"
cidr = "10.2.0.0/16"
azs = ["ap-northeast-1a", "ap-northeast-1b",
"ap-northeast-1c"]
public_subnets = ["10.2.1.0/24", "10.2.2.0/24,
"10.2.3.0/24]
# prod/local.tfvars
region = "ap-south-1"
country = "mena"
# prod/terraform.tfvars
terragrunt = {
terraform {
source = "network"
}
include = {
path = "${find_in_parent_folders()}"
}
}
name = "vpc-prd-mena"
cidr = "10.3.0.0/16"
azs = ["ap-south-1a", "ap-south-1b",
"ap-south-1c"]
public_subnets = ["10.3.1.0/24", "10.3.2.0/24,
"10.3.3.0/24]
output 참조
#local.tfvars
namespace = "prod"
stage = "kor"
aws_region = "ap-northeast-2"
# remote state key
vpc_remote_state_key = "prod/kor/xxx/terraform.tfstate"
#data.tf
data "terraform_remote_state" "vpc" {
backend = "s3"
config {
bucket = "${var.bucket}"
key = "${var.vpc_remote_state_key}"
region = "${var.config_region}"
encrypt = true
dynamodb_table = "${var.dynamodb_table}"
acl = "bucket-owner-full-control"
}
# https://www.terraform.io/docs/providers/consul/index.html
backend = "consul"
config {
address = "${var.consul_address}"
path = "${var.vpc_remote_state_key}"
datacenter = "${var.datacenter}"
}
}
# global.tfvars
profile = "prod"
Dependencies between modules
terragrunt = {
terraform {
source = "../../../modules//services//was"
}
include = {
path = "${find_in_parent_folders()}"
}
dependencies {
paths = ["../network"]
}
}
...
주의 (主義)
Terragrunt up-all 실행시 Dependencies까지 함께
생성됨.
하지만 all로 생성된 모듈을 destroy 을 할 경우
같이 생성 된 dependencies 까지 삭제 함.
Terraform & Terragrunt Code Version
terragrunt = {
terraform {
source =
"git::ssh://git@github.com/tf-service-repo.git?ref=rel
ease/v0.0.1//api"
}
include = {
path = "${find_in_parent_folders()}"
}
...
module "api" {
source =
"git::ssh://git@github.com//tf-module-repo.git?ref=r
elease/v0.0.1//ec2"
instance_count = "${var.instance_count}"
instance_type = "${var.instance_type}"
associate_public_ip_address =
"${var.associate_public_ip_address}"
subnet_ids =
["${data.aws_subnet.subnet.*.id}"]
...
Terraform Module Layer Service Layer Terragrunt Layer
Terraform & Terragrunt Structure
Terraform Module Repo Service Repo Terragrunt Repo
고민
● Terraform 통한 인프라 구성이 빠르지 않다
○ Terraform 코드 개발 및 검증
○ Terraform Learning cove
○ 손으로 작업 했던 경험
○ 이상과 현실
● Terragrunt도 사용해야 한다.
○ Terraform Enterprise에는 Terragrunt에서 제공하는 대분분의 기능을 제공한다던데...
손은 (눈)코드보다 빠르다
숙제
● Terraform 모듈 테스트 및 검증
○ CI pipeline 통한 모듈 테스트 도입
● PRD 환경 적용 후 리소스 삭제 방지
○ Terraform Lifecycle 설정
○ plan 통한 생성 및 삭제 리뷰 프로세스 수립
● tfstate 파일 시각화
○ tfstate 변경 이력 관리 (Terraboard 도입)
● Data Security (ssh key, password)
○ Vault, Consul 통한 데이터 보안
정리
● “상용 수준 인프라를 구성하고 운영 하는 것은 매우 어렵다”것 인지 하자.
● (AWS) 기본 디자인을 잘 하자.
● DRY를 실천하기 위해 노력 하자.
○ 한 곳에 너무 많은 리소스를 정의 하지 말자.
○ 중복을 최소화하고, 최대한 작게 서로 독립적으로 단순하게 구성 하자.
● 팀에서의 강력한 의지가 없다면 하지 말자.. (아무리 좋아도 관리 안되면 허사)
● 불확성(외부 요구 사항)에 대한 보다 유연한 대응을 위해 노력해야 합니다.
Spoon Radio Infra Member
● 노가다를 싫어하는 노땅 엔지니어 2명
● 묵묵히 열심히 달려주는 엔지니어 1명
● 그리고 함께 경험 하실 분 모십니다.
Reference
● https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
● https://charity.wtf/2016/03/30/terraform-vpc-and-why-you-want-a-tfstate-file-per-env/
● https://blog.gruntwork.io/5-lessons-learned-from-writing-over-300-000-lines-of-infrastructure-code-36ba7fadeac1
● https://www.slideshare.net/AntonBabenko/terraform-modules-and-some-of-bestpractices-march-2019
● https://qiita.com/billthelizard/items/9e113f3f569db4f569a5
● https://registry.terraform.io/modules/terraform-aws-modules/vpc/aws/2.7.0
● https://caylent.com/devops-and-dry/
● https://techblog.gumgum.com/articles/introducing-terraform-at-gumgum
● https://blog.gruntwork.io/
● https://www.slideshare.net/AntonBabenko/terraform-modules-and-some-of-bestpractices-march-2019
● https://charity.wtf/2016/03/30/terraform-vpc-and-why-you-want-a-tfstate-file-per-env/
● https://www.44bits.io/ko/post/terraform_introduction_infrastrucute_as_code
감사합니다.

More Related Content

What's hot

Automatizando ideas con Apache Airflow
Automatizando ideas con Apache AirflowAutomatizando ideas con Apache Airflow
Automatizando ideas con Apache AirflowSoftware Guru
 
마이크로서비스를 위한 AWS 아키텍처 패턴 및 모범 사례 - AWS Summit Seoul 2017
마이크로서비스를 위한 AWS 아키텍처 패턴 및 모범 사례 - AWS Summit Seoul 2017마이크로서비스를 위한 AWS 아키텍처 패턴 및 모범 사례 - AWS Summit Seoul 2017
마이크로서비스를 위한 AWS 아키텍처 패턴 및 모범 사례 - AWS Summit Seoul 2017Amazon Web Services Korea
 
CloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 Gaming
CloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 GamingCloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 Gaming
CloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 GamingAmazon Web Services Korea
 
[DEVIEW 2021] 1000만 글로벌 유저를 지탱하는 기술과 사람들
[DEVIEW 2021] 1000만 글로벌 유저를 지탱하는 기술과 사람들[DEVIEW 2021] 1000만 글로벌 유저를 지탱하는 기술과 사람들
[DEVIEW 2021] 1000만 글로벌 유저를 지탱하는 기술과 사람들Brian Hong
 
Kubernetes & helm 활용
Kubernetes & helm 활용Kubernetes & helm 활용
Kubernetes & helm 활용SK Telecom
 
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기SeungYong Oh
 
Kubernetes Forum Seoul 2019: Re-architecting Data Platform with Kubernetes
Kubernetes Forum Seoul 2019: Re-architecting Data Platform with KubernetesKubernetes Forum Seoul 2019: Re-architecting Data Platform with Kubernetes
Kubernetes Forum Seoul 2019: Re-architecting Data Platform with KubernetesSeungYong Oh
 
[AWS Dev Day] 앱 현대화 | AWS Fargate를 사용한 서버리스 컨테이너 활용 하기 - 삼성전자 개발자 포털 사례 - 정영준...
[AWS Dev Day] 앱 현대화 | AWS Fargate를 사용한 서버리스 컨테이너 활용 하기 - 삼성전자 개발자 포털 사례 - 정영준...[AWS Dev Day] 앱 현대화 | AWS Fargate를 사용한 서버리스 컨테이너 활용 하기 - 삼성전자 개발자 포털 사례 - 정영준...
[AWS Dev Day] 앱 현대화 | AWS Fargate를 사용한 서버리스 컨테이너 활용 하기 - 삼성전자 개발자 포털 사례 - 정영준...Amazon Web Services Korea
 
AWS로 게임의 공통 기능 개발하기! - 채민관, 김민석, 한준식 :: AWS Game Master 온라인 세미나 #2
AWS로 게임의 공통 기능 개발하기! - 채민관, 김민석, 한준식 :: AWS Game Master 온라인 세미나 #2AWS로 게임의 공통 기능 개발하기! - 채민관, 김민석, 한준식 :: AWS Game Master 온라인 세미나 #2
AWS로 게임의 공통 기능 개발하기! - 채민관, 김민석, 한준식 :: AWS Game Master 온라인 세미나 #2Amazon Web Services Korea
 
Fargate 를 이용한 ECS with VPC 1부
Fargate 를 이용한 ECS with VPC 1부Fargate 를 이용한 ECS with VPC 1부
Fargate 를 이용한 ECS with VPC 1부Hyun-Mook Choi
 
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개if kakao
 
컨테이너 및 서버리스를 위한 효율적인 CI/CD 아키텍처 구성하기 - 현창훈 데브옵스 엔지니어, Flex / 송주영 데브옵스 엔지니어, W...
컨테이너 및 서버리스를 위한 효율적인 CI/CD 아키텍처 구성하기 - 현창훈 데브옵스 엔지니어, Flex / 송주영 데브옵스 엔지니어, W...컨테이너 및 서버리스를 위한 효율적인 CI/CD 아키텍처 구성하기 - 현창훈 데브옵스 엔지니어, Flex / 송주영 데브옵스 엔지니어, W...
컨테이너 및 서버리스를 위한 효율적인 CI/CD 아키텍처 구성하기 - 현창훈 데브옵스 엔지니어, Flex / 송주영 데브옵스 엔지니어, W...Amazon Web Services Korea
 
Kubernetes Security
Kubernetes SecurityKubernetes Security
Kubernetes Securityinovex GmbH
 
[115]쿠팡 서비스 클라우드 마이그레이션 통해 배운것들
[115]쿠팡 서비스 클라우드 마이그레이션 통해 배운것들[115]쿠팡 서비스 클라우드 마이그레이션 통해 배운것들
[115]쿠팡 서비스 클라우드 마이그레이션 통해 배운것들NAVER D2
 
숨겨진 마이크로서비스: 초고속 응답과 고가용성을 위한 캐시 서비스 디자인
숨겨진 마이크로서비스: 초고속 응답과 고가용성을 위한 캐시 서비스 디자인숨겨진 마이크로서비스: 초고속 응답과 고가용성을 위한 캐시 서비스 디자인
숨겨진 마이크로서비스: 초고속 응답과 고가용성을 위한 캐시 서비스 디자인VMware Tanzu Korea
 

What's hot (20)

Automatizando ideas con Apache Airflow
Automatizando ideas con Apache AirflowAutomatizando ideas con Apache Airflow
Automatizando ideas con Apache Airflow
 
Docker Kubernetes Istio
Docker Kubernetes IstioDocker Kubernetes Istio
Docker Kubernetes Istio
 
마이크로서비스를 위한 AWS 아키텍처 패턴 및 모범 사례 - AWS Summit Seoul 2017
마이크로서비스를 위한 AWS 아키텍처 패턴 및 모범 사례 - AWS Summit Seoul 2017마이크로서비스를 위한 AWS 아키텍처 패턴 및 모범 사례 - AWS Summit Seoul 2017
마이크로서비스를 위한 AWS 아키텍처 패턴 및 모범 사례 - AWS Summit Seoul 2017
 
CloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 Gaming
CloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 GamingCloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 Gaming
CloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 Gaming
 
[DEVIEW 2021] 1000만 글로벌 유저를 지탱하는 기술과 사람들
[DEVIEW 2021] 1000만 글로벌 유저를 지탱하는 기술과 사람들[DEVIEW 2021] 1000만 글로벌 유저를 지탱하는 기술과 사람들
[DEVIEW 2021] 1000만 글로벌 유저를 지탱하는 기술과 사람들
 
Kubernetes & helm 활용
Kubernetes & helm 활용Kubernetes & helm 활용
Kubernetes & helm 활용
 
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
 
Kubernetes Forum Seoul 2019: Re-architecting Data Platform with Kubernetes
Kubernetes Forum Seoul 2019: Re-architecting Data Platform with KubernetesKubernetes Forum Seoul 2019: Re-architecting Data Platform with Kubernetes
Kubernetes Forum Seoul 2019: Re-architecting Data Platform with Kubernetes
 
Final terraform
Final terraformFinal terraform
Final terraform
 
[AWS Dev Day] 앱 현대화 | AWS Fargate를 사용한 서버리스 컨테이너 활용 하기 - 삼성전자 개발자 포털 사례 - 정영준...
[AWS Dev Day] 앱 현대화 | AWS Fargate를 사용한 서버리스 컨테이너 활용 하기 - 삼성전자 개발자 포털 사례 - 정영준...[AWS Dev Day] 앱 현대화 | AWS Fargate를 사용한 서버리스 컨테이너 활용 하기 - 삼성전자 개발자 포털 사례 - 정영준...
[AWS Dev Day] 앱 현대화 | AWS Fargate를 사용한 서버리스 컨테이너 활용 하기 - 삼성전자 개발자 포털 사례 - 정영준...
 
AWS Blackbelt 2015シリーズ AWS Lambda
AWS Blackbelt 2015シリーズ AWS LambdaAWS Blackbelt 2015シリーズ AWS Lambda
AWS Blackbelt 2015シリーズ AWS Lambda
 
01. Kubernetes-PPT.pptx
01. Kubernetes-PPT.pptx01. Kubernetes-PPT.pptx
01. Kubernetes-PPT.pptx
 
AWS로 게임의 공통 기능 개발하기! - 채민관, 김민석, 한준식 :: AWS Game Master 온라인 세미나 #2
AWS로 게임의 공통 기능 개발하기! - 채민관, 김민석, 한준식 :: AWS Game Master 온라인 세미나 #2AWS로 게임의 공통 기능 개발하기! - 채민관, 김민석, 한준식 :: AWS Game Master 온라인 세미나 #2
AWS로 게임의 공통 기능 개발하기! - 채민관, 김민석, 한준식 :: AWS Game Master 온라인 세미나 #2
 
Fargate 를 이용한 ECS with VPC 1부
Fargate 를 이용한 ECS with VPC 1부Fargate 를 이용한 ECS with VPC 1부
Fargate 를 이용한 ECS with VPC 1부
 
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
 
컨테이너 및 서버리스를 위한 효율적인 CI/CD 아키텍처 구성하기 - 현창훈 데브옵스 엔지니어, Flex / 송주영 데브옵스 엔지니어, W...
컨테이너 및 서버리스를 위한 효율적인 CI/CD 아키텍처 구성하기 - 현창훈 데브옵스 엔지니어, Flex / 송주영 데브옵스 엔지니어, W...컨테이너 및 서버리스를 위한 효율적인 CI/CD 아키텍처 구성하기 - 현창훈 데브옵스 엔지니어, Flex / 송주영 데브옵스 엔지니어, W...
컨테이너 및 서버리스를 위한 효율적인 CI/CD 아키텍처 구성하기 - 현창훈 데브옵스 엔지니어, Flex / 송주영 데브옵스 엔지니어, W...
 
AWS Fargate on EKS 실전 사용하기
AWS Fargate on EKS 실전 사용하기AWS Fargate on EKS 실전 사용하기
AWS Fargate on EKS 실전 사용하기
 
Kubernetes Security
Kubernetes SecurityKubernetes Security
Kubernetes Security
 
[115]쿠팡 서비스 클라우드 마이그레이션 통해 배운것들
[115]쿠팡 서비스 클라우드 마이그레이션 통해 배운것들[115]쿠팡 서비스 클라우드 마이그레이션 통해 배운것들
[115]쿠팡 서비스 클라우드 마이그레이션 통해 배운것들
 
숨겨진 마이크로서비스: 초고속 응답과 고가용성을 위한 캐시 서비스 디자인
숨겨진 마이크로서비스: 초고속 응답과 고가용성을 위한 캐시 서비스 디자인숨겨진 마이크로서비스: 초고속 응답과 고가용성을 위한 캐시 서비스 디자인
숨겨진 마이크로서비스: 초고속 응답과 고가용성을 위한 캐시 서비스 디자인
 

Similar to Configuring global infrastructure in terraform

Terraform을 이용한 Infrastructure as Code 실전 구성하기 :: 변정훈::AWS Summit Seoul 2018
 Terraform을 이용한 Infrastructure as Code 실전 구성하기 :: 변정훈::AWS Summit Seoul 2018 Terraform을 이용한 Infrastructure as Code 실전 구성하기 :: 변정훈::AWS Summit Seoul 2018
Terraform을 이용한 Infrastructure as Code 실전 구성하기 :: 변정훈::AWS Summit Seoul 2018Amazon Web Services Korea
 
Terraform을 이용한 Infrastructure as Code 실전 구성하기
Terraform을 이용한 Infrastructure as Code 실전 구성하기Terraform을 이용한 Infrastructure as Code 실전 구성하기
Terraform을 이용한 Infrastructure as Code 실전 구성하기JeongHun Byeon
 
Apache ZooKeeper 소개
Apache ZooKeeper 소개Apache ZooKeeper 소개
Apache ZooKeeper 소개중선 곽
 
Klug pacemaker the opensource high-availability_1.0_f
Klug pacemaker the opensource high-availability_1.0_fKlug pacemaker the opensource high-availability_1.0_f
Klug pacemaker the opensource high-availability_1.0_f동현 김
 
제3회난공불락 오픈소스 인프라세미나 - Pacemaker
제3회난공불락 오픈소스 인프라세미나 - Pacemaker제3회난공불락 오픈소스 인프라세미나 - Pacemaker
제3회난공불락 오픈소스 인프라세미나 - PacemakerTommy Lee
 
Programming Cascading
Programming CascadingProgramming Cascading
Programming CascadingTaewook Eom
 
[오픈소스컨설팅] Open stack kilo with DVR_CEPH_v1.1
[오픈소스컨설팅] Open stack kilo with DVR_CEPH_v1.1[오픈소스컨설팅] Open stack kilo with DVR_CEPH_v1.1
[오픈소스컨설팅] Open stack kilo with DVR_CEPH_v1.1Ji-Woong Choi
 
Openstack live migration
Openstack live migrationOpenstack live migration
Openstack live migrationymtech
 
NodeJs로 디바이스 통신하기
NodeJs로 디바이스 통신하기NodeJs로 디바이스 통신하기
NodeJs로 디바이스 통신하기TaeYoung Kim
 
[드론] 펌웨어 분석 [2015.5.23]
[드론] 펌웨어 분석 [2015.5.23][드론] 펌웨어 분석 [2015.5.23]
[드론] 펌웨어 분석 [2015.5.23]chcbaram
 
Startup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSStartup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSCirculus
 
하이퍼레저 페이지 단위 블록 조회
하이퍼레저 페이지 단위 블록 조회하이퍼레저 페이지 단위 블록 조회
하이퍼레저 페이지 단위 블록 조회wonyong hwang
 
[232] 수퍼컴퓨팅과 데이터 어낼리틱스
[232] 수퍼컴퓨팅과 데이터 어낼리틱스[232] 수퍼컴퓨팅과 데이터 어낼리틱스
[232] 수퍼컴퓨팅과 데이터 어낼리틱스NAVER D2
 
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안Jeongsang Baek
 
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020Ji-Woong Choi
 
[오픈소스컨설팅]Nginx jboss 연동가이드__v1
[오픈소스컨설팅]Nginx jboss 연동가이드__v1[오픈소스컨설팅]Nginx jboss 연동가이드__v1
[오픈소스컨설팅]Nginx jboss 연동가이드__v1Ji-Woong Choi
 
[225]빅데이터를 위한 분산 딥러닝 플랫폼 만들기
[225]빅데이터를 위한 분산 딥러닝 플랫폼 만들기[225]빅데이터를 위한 분산 딥러닝 플랫폼 만들기
[225]빅데이터를 위한 분산 딥러닝 플랫폼 만들기NAVER D2
 
[2014 CodeEngn Conference 11] 이경식 - 동적 추적 프레임워크를 이용한 OS X 바이너리 분석
[2014 CodeEngn Conference 11] 이경식 - 동적 추적 프레임워크를 이용한 OS X 바이너리 분석[2014 CodeEngn Conference 11] 이경식 - 동적 추적 프레임워크를 이용한 OS X 바이너리 분석
[2014 CodeEngn Conference 11] 이경식 - 동적 추적 프레임워크를 이용한 OS X 바이너리 분석GangSeok Lee
 

Similar to Configuring global infrastructure in terraform (20)

Terraform을 이용한 Infrastructure as Code 실전 구성하기 :: 변정훈::AWS Summit Seoul 2018
 Terraform을 이용한 Infrastructure as Code 실전 구성하기 :: 변정훈::AWS Summit Seoul 2018 Terraform을 이용한 Infrastructure as Code 실전 구성하기 :: 변정훈::AWS Summit Seoul 2018
Terraform을 이용한 Infrastructure as Code 실전 구성하기 :: 변정훈::AWS Summit Seoul 2018
 
Terraform을 이용한 Infrastructure as Code 실전 구성하기
Terraform을 이용한 Infrastructure as Code 실전 구성하기Terraform을 이용한 Infrastructure as Code 실전 구성하기
Terraform을 이용한 Infrastructure as Code 실전 구성하기
 
Apache ZooKeeper 소개
Apache ZooKeeper 소개Apache ZooKeeper 소개
Apache ZooKeeper 소개
 
Klug pacemaker the opensource high-availability_1.0_f
Klug pacemaker the opensource high-availability_1.0_fKlug pacemaker the opensource high-availability_1.0_f
Klug pacemaker the opensource high-availability_1.0_f
 
제3회난공불락 오픈소스 인프라세미나 - Pacemaker
제3회난공불락 오픈소스 인프라세미나 - Pacemaker제3회난공불락 오픈소스 인프라세미나 - Pacemaker
제3회난공불락 오픈소스 인프라세미나 - Pacemaker
 
Programming Cascading
Programming CascadingProgramming Cascading
Programming Cascading
 
[오픈소스컨설팅] Open stack kilo with DVR_CEPH_v1.1
[오픈소스컨설팅] Open stack kilo with DVR_CEPH_v1.1[오픈소스컨설팅] Open stack kilo with DVR_CEPH_v1.1
[오픈소스컨설팅] Open stack kilo with DVR_CEPH_v1.1
 
Openstack live migration
Openstack live migrationOpenstack live migration
Openstack live migration
 
NodeJs로 디바이스 통신하기
NodeJs로 디바이스 통신하기NodeJs로 디바이스 통신하기
NodeJs로 디바이스 통신하기
 
KAFKA 3.1.0.pdf
KAFKA 3.1.0.pdfKAFKA 3.1.0.pdf
KAFKA 3.1.0.pdf
 
[드론] 펌웨어 분석 [2015.5.23]
[드론] 펌웨어 분석 [2015.5.23][드론] 펌웨어 분석 [2015.5.23]
[드론] 펌웨어 분석 [2015.5.23]
 
Startup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSStartup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JS
 
하이퍼레저 페이지 단위 블록 조회
하이퍼레저 페이지 단위 블록 조회하이퍼레저 페이지 단위 블록 조회
하이퍼레저 페이지 단위 블록 조회
 
[232] 수퍼컴퓨팅과 데이터 어낼리틱스
[232] 수퍼컴퓨팅과 데이터 어낼리틱스[232] 수퍼컴퓨팅과 데이터 어낼리틱스
[232] 수퍼컴퓨팅과 데이터 어낼리틱스
 
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
 
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
 
[오픈소스컨설팅]Nginx jboss 연동가이드__v1
[오픈소스컨설팅]Nginx jboss 연동가이드__v1[오픈소스컨설팅]Nginx jboss 연동가이드__v1
[오픈소스컨설팅]Nginx jboss 연동가이드__v1
 
[225]빅데이터를 위한 분산 딥러닝 플랫폼 만들기
[225]빅데이터를 위한 분산 딥러닝 플랫폼 만들기[225]빅데이터를 위한 분산 딥러닝 플랫폼 만들기
[225]빅데이터를 위한 분산 딥러닝 플랫폼 만들기
 
[2014 CodeEngn Conference 11] 이경식 - 동적 추적 프레임워크를 이용한 OS X 바이너리 분석
[2014 CodeEngn Conference 11] 이경식 - 동적 추적 프레임워크를 이용한 OS X 바이너리 분석[2014 CodeEngn Conference 11] 이경식 - 동적 추적 프레임워크를 이용한 OS X 바이너리 분석
[2014 CodeEngn Conference 11] 이경식 - 동적 추적 프레임워크를 이용한 OS X 바이너리 분석
 
Scala for play
Scala for playScala for play
Scala for play
 

Configuring global infrastructure in terraform

  • 1. 테라폼으로 글로벌 서비스 구성 - DRY 체험기 - devops@mykoon.com
  • 2. Spoon Radio Infra Member ● 노가다를 싫어하는 노땅 엔지니어 2명 ○ 최상기(Martin): https://www.linkedin.com/in/sanggi-choi/ ○ 백영진(Paul): https://www.linkedin.com/in/youngjin-baek-8a2a74a4/ ● 묵묵히 열심히 겁나게 달려주는 엔지니어 1명 ○ 박민호(Ash): https://www.linkedin.com/in/park-minho-4896b7117/
  • 3. Agenda ● Spoon Radio 소개 ● 요구 사항 ● 인프라 구성 도구 ● 코드 중복 극복기 (DRY Journey) ○ Phase 1: Terraform ○ Phase 2: Terraform Module ○ Phase 3: Terragrunt ○ 고민 ○ 숙제 ● 정리
  • 4. SPOON RADIO ● 개요: 개인 오디오 라이브 스트리밍 모바일 플랫폼 ● 특징: 10 ~ 20대를 타겟팅 한 모바일 미디어 채널 ● 2016년(한국), 2017년(인도네시아/베트남), 2018년(일본/중동 GCC 5개국) ● 글로벌 다운로드 900만 / 글로벌 MAU 170만
  • 5. 6개월 간의 중복 코드 탈출기(ing) ● WET: Write Everything Twice ○ 중복, 반복된 코드 ○ 수정 및 재 활용 하는데 많은 비용 발생 ● DRY: Don't Repeat Yourself ○ 품질과 무결성 확보 ○ 읽기 쉽고 ○ 재활용 가능 ○ 수정 및 활용 하는데 비용이 낮음.
  • 6. 요구 사항 ● 보통 인프라 구조는 거의 유사하지만, 아주 약간 다른 환경 구성 관리를 해야 함. ○ multiple aws accounts & region , environments, ○ aws resource(IAM, VPC, Subnet, RDS, EC2, Aurora, ALB, Lambda, S3, Route53 and so on.) => 5개국 서비스 구성시 15개의 유사 인프라 구성과 관리 ● 기존 Legacy Infra를 Code 기반으로 자동화 ○ AWS Well-Architected & ISMS & ISO27001 대응 인프라 구성 ○ 생산성이 높은 인프라 환경 구성
  • 7. 인프라 구성 도구 Code Repository Infrastructure Provisioning Image Management Configuration Management CI/CD Code Repository (Terraform, Packer, AWX, Ansible, Dockerfile..etc) AWS Infrastructure (VPC, Subnet, Security Group, IAM, S3.. etc) AWS AMI Base Image (Amazon Linux, Ubuntu, CentOS..etc) Software Provisioning (Nginx,Python,Java, Docker..etc) Continuous Integration & Delivery (Terraform, Packer, Application, Web) Terragrunt
  • 8. Phase 1 - Terraform ● IaC - 인프라 생성, 변경, 설정을 코드 관리 ○ 비용의 감소(돈, 인력, 노력 등) ○ 빠른 실행 속도 ○ 위험 관리 ○ 불확실성에 대한 유연함 - 아는 만큼 보이고, 처음 부터 완벽할 수 없다. ● Terraform ○ Terraform은 HashiCprop에서 만든 오픈 소스 도구이며, 인프라를 코드 형태로 정의하는 간편한 선언형 프로그래밍 언어 ■ Multi Provider ■ Large Community ○ 그냥 해 보고 싶었다.
  • 9. Phase 1 - 시작 ● VPC ● Subnet ● Route Table ● IGW ● NAT
  • 10. Phase 1 - 단순 리소스 나열 # kor/main.tf provider "aws" { region = "ap-northeast-2" access_key ="XXXXXXXXXXXXXXXX" secert_key ="XXXXXXXXXXXXXXXX" } resource "aws_vpc" "test-vpc" { cidr_block = "10.1.0.0/16" instance_tenancy = "default" enable_dns_support = "true" enable_dns_hostnames = "true" enable_classiclink = "false" tags { Name = "test-vpc" } } resource "aws_subnet" "public-subnet-2a" { vpc_id = "${aws_vpc.test-vpc.id}" cidr_block = "10.1.1.0/24" map_public_ip_on_launch = "true" availability_zone = "ap-northeast-2a" tags { Name = "public-subnet-2a" } } resource "aws_subnet" "private-subnet-2a" { vpc_id = "${aws_vpc.test-vpc.id}" cidr_block = "10.1.2.0/24" map_public_ip_on_launch = "false" availability_zone = "ap-northeast-2a" tags { Name = "private-subnet-2a" } } resource "aws_internet_gateway" "gw" { vpc_id = "${aws_vpc.test-vpc.id}" tags { Name = "internet-gateway" } } resource "aws_route_table" "rt1" { vpc_id = "${aws_vpc.test-vpc.id}" route { cidr_block = "0.0.0.0/0" gateway_id = "${aws_internet_gateway.gw.id}" } tags { Name = "Default" } } resource "aws_route_table_association" "association-subnet" { subnet_id = "${aws_subnet.public-1.id}" route_table_id = "${aws_route_table.rt1.id}" } output "vpc-id" { value = "${aws_vpc.test-vpc.id}" } output "vpc-public-subnet-cidr" { value = "${aws_subnet.public-subnet-2a.cidr_block}" } output "vpc-public-subnet-id" { value = "${aws_subnet.public-subnet-2a.id}" } output "vpc-private-subnet-cidr" { value = "${aws_subnet.private-subnet-2a.cidr_block}" } output "vpc-private-subnet-id" { value = "${aws_subnet.private-subnet-2a.id}" }
  • 11. Phase 1 - main.tf 중복 KR JP IN VE MENA + PRD - main.tf + STG - main.tf + DEV - main.tf + PRD - main.tf + STG - main.tf + DEV - main.tf + PRD - main.tf + STG - main.tf + DEV - main.tf + PRD - main.tf + STG - main.tf + DEV - main.tf + PRD - main.tf + STG - main.tf + DEV - main.tf ● 5개 국가, 3개의 인프라 환경 => 총 15개의 인프라 환경을 구성 관리해야 함. ○ 국가, 환경은 다르지만 동일한 인프라 구조를 만들기 위한 중복되는 옵션의 resource가 다수 발생. ○ 대략 100 ~ 200 line 수준의 main.tf WET Code 발생.
  • 12. Phase 1 - 결국 ● 단순 리소스 나열만으로는 15벌 인프라 전개 불가능 ○ 재활용이 불가능 ○ 비슷한 리소스의 대량 중복 발생 ○ 유지 보수 불가능 ○ 이렇게 할 거면 Hands - On과 차이가....
  • 13. Phase 2 - Terraform Module ● Data를 변수 처리한 리소스 구성 파일 묶음. ○ 비슷한 리소스를 반복 정의하는 고통에서 벗어날 수 있다. ○ 사용자 정의 모듈 만들어 활용 ○ 외부에서 이미 잘 만들어둔 모듈 활용 ■ https://registry.terraform.io/ ■ https://github.com/cloudposse ■ https://github.com/terraform-aws-modules ○ 리소스에는 versioning이 안되지만, 모듈에는 버저닝 가능 -> 모듈간 독립성 확보(의존성 제거)
  • 14. Phase 2 - 시도 # terraform-aws-vpc/main.tf locals { max_subnet_length = max( length(var.private_subnets), length(var.elasticache subnets), length(var.database_subnets), length(var.redshift_subnets), ) nat_gateway_count = var.single_nat_gateway ? 1 : var.one_nat_gateway_per_az ? length(var.azs) : local.max_subnet_length ………… 길어요... # prd-kr/main.tf terraform { backend "s3" { bucket = "backend-bucket" key = "prd-kr-vpc/terraform.tfstate" region = "ap-northeast-2" profile = "prd-kr" } } provider aws { region = "ap-northeast-2" profile = "prd" } module "network" { source = "../modules/network" name = "${var.name}" cidr = "${var.cidr}" azs = "${var.azs}" public_subnets = "${var.public_subnets}" env = "${var.env}" } # prd-kr/vars.tf variable name { type = "string" default = "" } variable cidr { type = "string" default = "0.0.0.0/0" } variable public_subnets { type = "list" default = ["0.0.0.0/0"] } variable private_subnets { type = "list" default = ["0.0.0.0/0"] } variable azs { type = "list" default = [""] } # prd-kr/terraform.tfvars name = "prd-kor-vpc" cidr = "10.1.0.0/16" public_subnets = ["10.1.1.0/24", ...] public_subnets = ["10.1.2.0/24", ...] asz = ["ap-northeast-2a", ...] env = "prd-kor
  • 15. vars.tf Duplicated main.tf Duplicated Phase 2 - Repeat Itself, Again ● module을 사용하면서 resource는 재활용이 가능해 졌지만, root module을 참조하는 sub module과 변수 정의 부분은 각 환경별 중복이 발생 ● terraform.tfvars을 제외한 곳에서 WET code 발생 # jpn/terraform.tfvars name = "prd-jpn-vpc" cidr = "10.2.0.0/16" public_subnets = ["10.2.0.0/24", ...] public_subnets = ["10.2.1.0/24", ...] asz = ["ap-northeast-2a", ...] env = "prd-kor # kor/terraform.tfvars name = "prd-kor-vpc" cidr = "10.1.0.0/16" public_subnets = ["10.1.1.0/24", ...] public_subnets = ["10.1.2.0/24", ...] asz = ["ap-northeast-2a", ...] env = "prd-kor # kor/main.tf module "network" { source = "../modules/network" name = "${var.name}" cidr = "${var.cidr}" azs = "${var.azs}" public_subnets = "${var.public_subnets}" env = "${var.env}" } # kor/vars.tf variable name { type = "string" default = "" } variable cidr { type = "string" default = "0.0.0.0/0" } # jpn/main.tf module "network" { source = "../modules/network" name = "${var.name}" cidr = "${var.cidr}" azs = "${var.azs}" public_subnets = "${var.public_subnets}" env = "${var.env}" } # jpn/vars.tf variable name { type = "string" default = "" } variable cidr { type = "string" default = "0.0.0.0/0" }
  • 16. Phase 2 - 세상에 공짜는 없다. ● multiple env에서 그래도 중복 발생(main.tf, var.tf) ○ 5개 국가, 3개 환경 구성에 대한 중복은 그대로 ○ global, local 변수 정의 관리 불편 ● 오픈소스 모듈도 결국 내 입맛에 맞게 수정 ○ 조금만 바꿔도 삭제 후 재 생성 ㅜㅜ ■ 요구 사항에 맞게 Lifecycle 관리 추가 ○ resource 생성을 모듈 하위에서 생성하기에 수정하기가 불가함 ○ 결국에 오픈소스 전체 코드 분석 후 수정함
  • 17. Phase 3 - Terragrunt ● gruntworks.io에서 개발하고, Terraform만으로는 부족한 기능 보완 ● 단순한 인프라는 Terraform으로도 충분하다. 그러나 인프라 구성이 커질 수록 모듈간의 연관 관계 및 중복 발생 ● Orchestration = Terragrunt ○ 모듈 간의 코드 중복을 최소화 ○ 모듈 간의 종속 관계 제거 Gruntwork.io
  • 18. Terragrunt 기본 구조 ● /terraform.tfvars ○ terragrunt의 환경설정 ● /globals.tfvars ○ root module ○ root vars ● locals.tfvars ○ sub module ○ sub vars ● terraform.tfvars ○ 각각의 vars terragrunt = { …. terraform { extra_arguments "-var-file" { commands = ["${get_terraform_commands_that_need_vars()}"] optional_var_files = [ "${get_tfvars_dir()}/${find_in_parent_folders("globals.tfvars", "ignore")}", "${get_tfvars_dir()}/${find_in_parent_folders("locals.tfvars", "ignore")}" ] } } } namespace = "prod" # dynamodb & s3 bucket = "prod-terraform-state" config_region = "ap-northeast-2" dynamodb_table = "prod-terraform-db" stage = "kor" aws_region = "ap-northeast-2" # remote state key vpc_remote_state_key = "prod/kor/terraform.tfstate" terragrunt = { terraform { source = "git::ssh/spooncast/terraform-service-repo.git?ref=release/v0.0.1//bastion" } include = { path = "${find_in_parent_folders()}" } } name = "bastion" instance_type = "t2.micro" cidr_office = "xxx.xxx.xxx.xxx/32"
  • 19. 코드와 데이터의 분리(Data Driven Design) # prod/main.tf terraform { # The configuration for this backend will be filled in by Terragrunt backend "s3" {} } provider aws { region = "${var.region}" profile = "${var.profile}" } module "network" { source = "terraform-aws-modules/vpc/aws" name = "${var.name}" cidr = "${var.cidr}" azs = "${var.azs}" public_subnets = "${var.public_subnets}" env = "${var.country}" } # global.tfvars profile = "prod" # prod/local.tfvars region = "ap-northeast-2" country = "kr" # prod/terraform.tfvars terragrunt = { terraform { source = "network" } include = { path = "${find_in_parent_folders()}" } } name = "vpc-prd-kor" cidr = "10.1.0.0/16" azs = ["ap-northeast-2a", "ap-northeast-2b", "ap-northeast-2c"] public_subnets = ["10.1.1.0/24", "10.1.2.0/24, "10.1.3.0/24] # prod/local.tfvars region = "ap-northeast-1" country = "jp" # prod/terraform.tfvars terragrunt = { terraform { source = "network" } include = { path = "${find_in_parent_folders()}" } } name = "vpc-prd-jp" cidr = "10.2.0.0/16" azs = ["ap-northeast-1a", "ap-northeast-1b", "ap-northeast-1c"] public_subnets = ["10.2.1.0/24", "10.2.2.0/24, "10.2.3.0/24] # prod/local.tfvars region = "ap-south-1" country = "mena" # prod/terraform.tfvars terragrunt = { terraform { source = "network" } include = { path = "${find_in_parent_folders()}" } } name = "vpc-prd-mena" cidr = "10.3.0.0/16" azs = ["ap-south-1a", "ap-south-1b", "ap-south-1c"] public_subnets = ["10.3.1.0/24", "10.3.2.0/24, "10.3.3.0/24]
  • 20. output 참조 #local.tfvars namespace = "prod" stage = "kor" aws_region = "ap-northeast-2" # remote state key vpc_remote_state_key = "prod/kor/xxx/terraform.tfstate" #data.tf data "terraform_remote_state" "vpc" { backend = "s3" config { bucket = "${var.bucket}" key = "${var.vpc_remote_state_key}" region = "${var.config_region}" encrypt = true dynamodb_table = "${var.dynamodb_table}" acl = "bucket-owner-full-control" } # https://www.terraform.io/docs/providers/consul/index.html backend = "consul" config { address = "${var.consul_address}" path = "${var.vpc_remote_state_key}" datacenter = "${var.datacenter}" } } # global.tfvars profile = "prod"
  • 21. Dependencies between modules terragrunt = { terraform { source = "../../../modules//services//was" } include = { path = "${find_in_parent_folders()}" } dependencies { paths = ["../network"] } } ... 주의 (主義) Terragrunt up-all 실행시 Dependencies까지 함께 생성됨. 하지만 all로 생성된 모듈을 destroy 을 할 경우 같이 생성 된 dependencies 까지 삭제 함.
  • 22. Terraform & Terragrunt Code Version terragrunt = { terraform { source = "git::ssh://git@github.com/tf-service-repo.git?ref=rel ease/v0.0.1//api" } include = { path = "${find_in_parent_folders()}" } ... module "api" { source = "git::ssh://git@github.com//tf-module-repo.git?ref=r elease/v0.0.1//ec2" instance_count = "${var.instance_count}" instance_type = "${var.instance_type}" associate_public_ip_address = "${var.associate_public_ip_address}" subnet_ids = ["${data.aws_subnet.subnet.*.id}"] ... Terraform Module Layer Service Layer Terragrunt Layer
  • 23. Terraform & Terragrunt Structure Terraform Module Repo Service Repo Terragrunt Repo
  • 24. 고민 ● Terraform 통한 인프라 구성이 빠르지 않다 ○ Terraform 코드 개발 및 검증 ○ Terraform Learning cove ○ 손으로 작업 했던 경험 ○ 이상과 현실 ● Terragrunt도 사용해야 한다. ○ Terraform Enterprise에는 Terragrunt에서 제공하는 대분분의 기능을 제공한다던데... 손은 (눈)코드보다 빠르다
  • 25. 숙제 ● Terraform 모듈 테스트 및 검증 ○ CI pipeline 통한 모듈 테스트 도입 ● PRD 환경 적용 후 리소스 삭제 방지 ○ Terraform Lifecycle 설정 ○ plan 통한 생성 및 삭제 리뷰 프로세스 수립 ● tfstate 파일 시각화 ○ tfstate 변경 이력 관리 (Terraboard 도입) ● Data Security (ssh key, password) ○ Vault, Consul 통한 데이터 보안
  • 26. 정리 ● “상용 수준 인프라를 구성하고 운영 하는 것은 매우 어렵다”것 인지 하자. ● (AWS) 기본 디자인을 잘 하자. ● DRY를 실천하기 위해 노력 하자. ○ 한 곳에 너무 많은 리소스를 정의 하지 말자. ○ 중복을 최소화하고, 최대한 작게 서로 독립적으로 단순하게 구성 하자. ● 팀에서의 강력한 의지가 없다면 하지 말자.. (아무리 좋아도 관리 안되면 허사) ● 불확성(외부 요구 사항)에 대한 보다 유연한 대응을 위해 노력해야 합니다.
  • 27. Spoon Radio Infra Member ● 노가다를 싫어하는 노땅 엔지니어 2명 ● 묵묵히 열심히 달려주는 엔지니어 1명 ● 그리고 함께 경험 하실 분 모십니다.
  • 28. Reference ● https://en.wikipedia.org/wiki/Don%27t_repeat_yourself ● https://charity.wtf/2016/03/30/terraform-vpc-and-why-you-want-a-tfstate-file-per-env/ ● https://blog.gruntwork.io/5-lessons-learned-from-writing-over-300-000-lines-of-infrastructure-code-36ba7fadeac1 ● https://www.slideshare.net/AntonBabenko/terraform-modules-and-some-of-bestpractices-march-2019 ● https://qiita.com/billthelizard/items/9e113f3f569db4f569a5 ● https://registry.terraform.io/modules/terraform-aws-modules/vpc/aws/2.7.0 ● https://caylent.com/devops-and-dry/ ● https://techblog.gumgum.com/articles/introducing-terraform-at-gumgum ● https://blog.gruntwork.io/ ● https://www.slideshare.net/AntonBabenko/terraform-modules-and-some-of-bestpractices-march-2019 ● https://charity.wtf/2016/03/30/terraform-vpc-and-why-you-want-a-tfstate-file-per-env/ ● https://www.44bits.io/ko/post/terraform_introduction_infrastrucute_as_code