SlideShare uma empresa Scribd logo
1 de 29
테라폼으로 글로벌 서비스
구성
- 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
감사합니다.

Mais conteúdo relacionado

Mais procurados

[OpenStack Days Korea 2016] Track1 - 카카오는 오픈스택 기반으로 어떻게 5000VM을 운영하고 있을까?
[OpenStack Days Korea 2016] Track1 - 카카오는 오픈스택 기반으로 어떻게 5000VM을 운영하고 있을까?[OpenStack Days Korea 2016] Track1 - 카카오는 오픈스택 기반으로 어떻게 5000VM을 운영하고 있을까?
[OpenStack Days Korea 2016] Track1 - 카카오는 오픈스택 기반으로 어떻게 5000VM을 운영하고 있을까?
OpenStack Korea Community
 

Mais procurados (20)

Clean architectures with fast api pycones
Clean architectures with fast api   pyconesClean architectures with fast api   pycones
Clean architectures with fast api pycones
 
Best Practices of Infrastructure as Code with Terraform
Best Practices of Infrastructure as Code with TerraformBest Practices of Infrastructure as Code with Terraform
Best Practices of Infrastructure as Code with Terraform
 
Terraform: An Overview & Introduction
Terraform: An Overview & IntroductionTerraform: An Overview & Introduction
Terraform: An Overview & Introduction
 
[OpenStack Days Korea 2016] Track1 - 카카오는 오픈스택 기반으로 어떻게 5000VM을 운영하고 있을까?
[OpenStack Days Korea 2016] Track1 - 카카오는 오픈스택 기반으로 어떻게 5000VM을 운영하고 있을까?[OpenStack Days Korea 2016] Track1 - 카카오는 오픈스택 기반으로 어떻게 5000VM을 운영하고 있을까?
[OpenStack Days Korea 2016] Track1 - 카카오는 오픈스택 기반으로 어떻게 5000VM을 운영하고 있을까?
 
Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門
 
Terraform
TerraformTerraform
Terraform
 
실전 서버 부하테스트 노하우
실전 서버 부하테스트 노하우 실전 서버 부하테스트 노하우
실전 서버 부하테스트 노하우
 
클라우드의 대세 쿠버네티스란 무엇인가?(윤성훈 클라우드 솔루션 아키텍트) - Webinar
클라우드의 대세 쿠버네티스란 무엇인가?(윤성훈 클라우드 솔루션 아키텍트) - Webinar클라우드의 대세 쿠버네티스란 무엇인가?(윤성훈 클라우드 솔루션 아키텍트) - Webinar
클라우드의 대세 쿠버네티스란 무엇인가?(윤성훈 클라우드 솔루션 아키텍트) - Webinar
 
Kubernetes & helm 활용
Kubernetes & helm 활용Kubernetes & helm 활용
Kubernetes & helm 활용
 
nexus helm 설치, docker/helm repo 설정과 예제
nexus helm 설치, docker/helm repo 설정과 예제nexus helm 설치, docker/helm repo 설정과 예제
nexus helm 설치, docker/helm repo 설정과 예제
 
[OpenStack] 공개 소프트웨어 오픈스택 입문 & 파헤치기
[OpenStack] 공개 소프트웨어 오픈스택 입문 & 파헤치기[OpenStack] 공개 소프트웨어 오픈스택 입문 & 파헤치기
[OpenStack] 공개 소프트웨어 오픈스택 입문 & 파헤치기
 
Final terraform
Final terraformFinal terraform
Final terraform
 
OpenStack Oslo Messaging RPC API Tutorial Demo Call, Cast and Fanout
OpenStack Oslo Messaging RPC API Tutorial Demo Call, Cast and FanoutOpenStack Oslo Messaging RPC API Tutorial Demo Call, Cast and Fanout
OpenStack Oslo Messaging RPC API Tutorial Demo Call, Cast and Fanout
 
Persistent Storage with Containers with Kubernetes & OpenShift
Persistent Storage with Containers with Kubernetes & OpenShiftPersistent Storage with Containers with Kubernetes & OpenShift
Persistent Storage with Containers with Kubernetes & OpenShift
 
[오픈소스컨설팅] 쿠버네티스와 쿠버네티스 on 오픈스택 비교 및 구축 방법
[오픈소스컨설팅] 쿠버네티스와 쿠버네티스 on 오픈스택 비교  및 구축 방법[오픈소스컨설팅] 쿠버네티스와 쿠버네티스 on 오픈스택 비교  및 구축 방법
[오픈소스컨설팅] 쿠버네티스와 쿠버네티스 on 오픈스택 비교 및 구축 방법
 
AWS Aurora 운영사례 (by 배은미)
AWS Aurora 운영사례 (by 배은미)AWS Aurora 운영사례 (by 배은미)
AWS Aurora 운영사례 (by 배은미)
 
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
 
Comprehensive Terraform Training
Comprehensive Terraform TrainingComprehensive Terraform Training
Comprehensive Terraform Training
 
Docker를 활용한 손쉬운 ECS 활용기 - 김민태 (AUSG) :: AWS Community Day Online 2021
Docker를 활용한 손쉬운 ECS 활용기 - 김민태 (AUSG) :: AWS Community Day Online 2021Docker를 활용한 손쉬운 ECS 활용기 - 김민태 (AUSG) :: AWS Community Day Online 2021
Docker를 활용한 손쉬운 ECS 활용기 - 김민태 (AUSG) :: AWS Community Day Online 2021
 
[GitOps] Argo CD on GKE (v0.9.2).pdf
[GitOps] Argo CD on GKE (v0.9.2).pdf[GitOps] Argo CD on GKE (v0.9.2).pdf
[GitOps] Argo CD on GKE (v0.9.2).pdf
 

Semelhante a Configuring global infrastructure in terraform

Semelhante a 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
 

Último

Último (8)

데이터 분석 문제 해결을 위한 나의 JMP 활용법
데이터 분석 문제 해결을 위한 나의 JMP 활용법데이터 분석 문제 해결을 위한 나의 JMP 활용법
데이터 분석 문제 해결을 위한 나의 JMP 활용법
 
JMP를 활용한 가속열화 분석 사례
JMP를 활용한 가속열화 분석 사례JMP를 활용한 가속열화 분석 사례
JMP를 활용한 가속열화 분석 사례
 
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
 
JMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
JMP를 활용한 전자/반도체 산업 Yield Enhancement MethodologyJMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
JMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
 
JMP가 걸어온 여정, 새로운 도약 JMP 18!
JMP가 걸어온 여정, 새로운 도약 JMP 18!JMP가 걸어온 여정, 새로운 도약 JMP 18!
JMP가 걸어온 여정, 새로운 도약 JMP 18!
 
공학 관점에서 바라본 JMP 머신러닝 최적화
공학 관점에서 바라본 JMP 머신러닝 최적화공학 관점에서 바라본 JMP 머신러닝 최적화
공학 관점에서 바라본 JMP 머신러닝 최적화
 
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
 
(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?
(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?
(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?
 

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