Only this pageAll pages
Powered by GitBook
1 of 15

ํ•œ๊ตญ์–ด (Korean)

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Terragrunt

์ฝ”๋“œ ๊ตฌ์กฐ ์˜ˆ์ œ

Terraform ์ฝ”๋“œ ๊ตฌ์กฐ

๋‹ค์Œ์˜ ์˜ˆ์ œ๋Š” AWS ํ”„๋กœ๋ฐ”์ด๋”๋ฅผ ๋ณด์—ฌ ์ฃผ์ง€๋งŒ ์˜ˆ์ œ์— ํ‘œ์‹œ๋œ ๋Œ€๋ถ€๋ถ„์˜ ์›์น™์€ ๋‹ค๋ฅธ ํผ๋ธ”๋ฆญ ํด๋ผ์šฐ๋“œ ๊ณต๊ธ‰์ž๋Š” ๋ฌผ๋ก  ๋‹ค๋ฅธ ์ข…๋ฅ˜์˜ ๊ณต๊ธ‰์ž(DNS, DB, ๋ชจ๋‹ˆํ„ฐ๋ง ๋“ฑ)์—๋„ ์ ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ ํ˜•
์„ค๋ช…
๊ฐ€์šฉ ์ƒํƒœ

๋ฆฌ์†Œ์Šค๊ฐ€ ์ ๊ณ  ์™ธ๋ถ€ ์˜์กด์„ฑ์ด ์—†์Œ. ๋‹จ์ผ AWS ๊ณ„์ •. ๋‹จ์ผ ์ง€์—ญ. ๋‹จ์ผ ํ™˜๊ฒฝ.

์˜ˆ

์—ฌ๋Ÿฌ AWS ๊ณ„์ • ๋ฐ ํ™˜๊ฒฝ, Terraform์„ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ์กด์˜ ์ธํ”„๋ผ ๋ชจ๋“ˆ

์˜ˆ

๋งŽ์€ AWS ๊ณ„์ •, ๋งŽ์€ ์ง€์—ญ, ๋ณต์‚ฌ-๋ถ™์—ฌ๋„ฃ๊ธฐ๋ฅผ ์ค„์ด๋Š” ์ผ์ด ์‹œ๊ธ‰ํ•จ, ์‚ฌ์šฉ์ž ์ง€์ • ์ธํ”„๋ผ ๋ชจ๋“ˆ, ๊ณผ๋„ํ•œ ๊ตฌ์„ฑ(composition) ์‚ฌ์šฉ. Terraform์„ ์‚ฌ์šฉ.

WIP

๋งค์šฐ ๋Œ€๊ทœ๋ชจ

์—ฌ๋Ÿฌ ๊ณต๊ธ‰์ž(AWS, GCP, Azure). ๋‹ค์ค‘ ํด๋ผ์šฐ๋“œ ๋ฐฐํฌ. Terraform์„ ์‚ฌ์šฉ.

์•„๋‹ˆ์˜ค

Terragrunt code structures

์œ ํ˜•
์„ค๋ช…
๊ฐ€์šฉ ์ƒํƒœ

์ค‘๊ฐ„ ๊ทœ๋ชจ

์—ฌ๋Ÿฌ AWS ๊ณ„์ • ๋ฐ ํ™˜๊ฒฝ, ๊ธฐ์กด ์ธํ”„๋ผ ๋ชจ๋“ˆ, Terrgrunt๋ฅผ ์‚ฌ์šฉํ•œ ๊ตฌ์„ฑ(composition) ํŒจํ„ด.

์•„๋‹ˆ์˜ค

๋Œ€๊ทœ๋ชจ

๋งŽ์€ AWS ๊ณ„์ •, ๋งŽ์€ ์ง€์—ญ, ๋ณต์‚ฌ-๋ถ™์—ฌ๋„ฃ๊ธฐ๋ฅผ ์ค„์ด๋Š” ์ผ์ด ์‹œ๊ธ‰ํ•จ, ์‚ฌ์šฉ์ž ์ง€์ • ์ธํ”„๋ผ ๋ชจ๋“ˆ, ๊ณผ๋„ํ•œ ๊ตฌ์„ฑ(composition) ์‚ฌ์šฉ. Terragrunt ์‚ฌ์šฉ.

์•„๋‹ˆ์˜ค

๋งค์šฐ ๋Œ€๊ทœ๋ชจ

์—ฌ๋Ÿฌ ํ”„๋กœ๋ฐ”์ด๋”(AWS, GCP, Azure), ๋ฉ€ํ‹ฐ ํด๋ผ์šฐ๋“œ ๋ฐฐํฌ, Terragrunt ์‚ฌ์šฉ.

์•„๋‹ˆ์˜ค

์†Œ๊ทœ๋ชจ
์ค‘๊ฐ„ ๊ทœ๋ชจ
๋Œ€๊ทœ๋ชจ

์›Œํฌ์ƒต

์ด ์•ˆ๋‚ด์„œ์— ์„ค๋ช…๋œ ๋‚ด์šฉ ์ค‘ ์ผ๋ถ€๋ฅผ ์—ฐ์Šตํ•˜๊ณ ์ž๋Š” ํ•˜๋Š” ๋ถ„๋“ค์„ ์œ„ํ•œ ์›Œํฌ์ˆ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚ด์šฉ์€ ์—ฌ๊ธฐ์— ์žˆ์Šต๋‹ˆ๋‹ค.

https://github.com/antonbabenko/terraform-best-practices-workshop

Terraform

์ฃผ์š” ๊ฐœ๋…

๊ณต์‹ Terraform ๋ฌธ์„œ๋Š” ๊ตฌ์„ฑ(configuration)์˜ ๋ชจ๋“  ์ธก๋ฉด์„ ์ž์„ธํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์ด ์„น์…˜์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์„ ์ดํ•ดํ•˜๋ ค๋ฉด ์ฃผ์˜ ๊นŠ๊ฒŒ ์ฝ์œผ์„ธ์š”

์ด ์„น์…˜์—์„œ๋Š” ์ด ์ฑ…์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ฃผ์š” ๊ฐœ๋…์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌ์†Œ์Šค(Resource)

๋ฆฌ์†Œ์Šค๋Š” is aws_vpc, aws_db_instance ๋“ฑ์ž…๋‹ˆ๋‹ค. ๋ฆฌ์†Œ์Šค๋Š” ์–ด๋А ํ•œ ํ”„๋กœ๋ฐ”์ด๋”์— ์†ํ•˜๋ฉฐ ์ธ์ˆ˜(arguments)๋ฅผ ์ˆ˜๋ฝํ•˜๊ณ  ์†์„ฑ(attributes)์„ ์ถœ๋ ฅ(output)ํ•˜๋ฉฐ ์ˆ˜๋ช… ์ฃผ๊ธฐ(lifecycle)๋ฅผ๊ฐ€์ง‘๋‹ˆ๋‹ค. ๋ฆฌ์†Œ์Šค๋Š” ์ƒ์„ฑ, ๊ฒ€์ƒ‰, ์—…๋ฐ์ดํŠธ ๋ฐ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ(Resource module)

๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ์€ ๊ณตํ†ต ์ž‘์—…(์˜ˆ: AWS VPC Terraform ๋ชจ๋“ˆ์ด VPC, ์„œ๋ธŒ๋„ท, NAT ๊ฒŒ์ดํŠธ์›จ์ด ๋“ฑ์„ ์ƒ์„ฑํ•จ)์„ ํ•จ๊ป˜ ์ˆ˜ํ–‰ํ•˜๋Š” ์—ฐ๊ฒฐ๋œ ๋ฆฌ์†Œ์Šค์˜ ์ง‘ํ•ฉ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๊ณต๊ธ‰์ž ๊ตฌ์„ฑ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋ฉฐ, ์ด๋Š” ๊ณต๊ธ‰์ž์˜ ๊ตฌ์„ฑ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๋ฉฐ, ๊ณต๊ธ‰์ž ๊ตฌ์„ฑ ์•ˆ์—์„œ ์ •์˜ํ•˜๊ฑฐ๋‚˜ ์ƒ์œ„ ์ˆ˜์ค€์˜ ๊ตฌ์กฐ(์˜ˆ: ์ธํ”„๋ผ ๋ชจ๋“ˆ)์—์„œ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ธํ”„๋ผ ๋ชจ๋“ˆ(Infrastructure module)

์ธํ”„๋ผ ๋ชจ๋“ˆ์€ ๋…ผ๋ฆฌ์ ์œผ๋กœ ์—ฐ๊ฒฐ๋˜์ง€๋Š” ์•Š์ง€๋งŒ ํ˜„์žฌ ์ƒํ™ฉ/ํ”„๋กœ์ ํŠธ/์…‹์—…์—์„œ ๋™์ผํ•œ ๋ชฉ์ ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ์˜ ์ง‘ํ•ฉ์ž…๋‹ˆ๋‹ค. ๊ณต๊ธ‰์ž์— ๋Œ€ํ•œ ๊ตฌ์„ฑ์„ ์ •์˜ํ•˜๊ณ  ๋‹ค์šด์ŠคํŠธ๋ฆผ ๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ ๋ฐ ๋ฆฌ์†Œ์Šค๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋…ผ๋ฆฌ์  ๊ตฌ๋ถ„์ž(์˜ˆ: AWS Region, Google Project)๋‹น ํ•˜๋‚˜์˜ ์—”ํ‹ฐํ‹ฐ์—์„œ ์ž‘์—…ํ•˜๋„๋ก ์ œํ•œ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด terraform-aws-atlantis ๋ชจ๋“ˆ์€ terraform-aws-vpc ๋ฐ terraform-aws-security-group๊ณผ ๊ฐ™์€ ๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ AWS Fargate์—์„œ Atlantis๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ธํ”„๋ผ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๋˜ ๋‹ค๋ฅธ ์˜ˆ๋กœ terraform-aws-modules ๋ชจ๋“ˆ์„ ์—ฌ๋Ÿฌ ๊ฐœ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ์ธํ”„๋ผ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ๋„์ปค ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋„์ปค ์ด๋ฏธ์ง€๋ฅผ ๊ตฌ์ถ•, ํ‘ธ์‹œ ๋ฐ ๋ฐฐํฌํ•˜๋Š” terraform-aws-cloudquery ๋ชจ๋“ˆ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ชจ๋“  ๊ฒƒ์ด ํ•œ ์„ธํŠธ๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.

๊ตฌ์„ฑ(Composition)

๊ตฌ์„ฑ์€ ๋…ผ๋ฆฌ์ ์œผ๋กœ ๋ถ„๋ฆฌ๋œ ์—ฌ๋Ÿฌ ์˜์—ญ(์˜ˆ: AWS ์ง€์—ญ, ์—ฌ๋Ÿฌ AWS ๊ณ„์ •)์— ๊ฑธ์ณ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋Š” ์ธํ”„๋ผ ๋ชจ๋“ˆ์˜ ๋ชจ์Œ์ž…๋‹ˆ๋‹ค. ๊ตฌ์„ฑ์€ ์ „์ฒด ์กฐ์ง์ด๋‚˜ ํ”„๋กœ์ ํŠธ์— ํ•„์š”ํ•œ ์ „์ฒด ์ธํ”„๋ผ๋ฅผ ์„ค๋ช…ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๊ตฌ์„ฑ์€ ๊ฐœ๋ณ„ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ๋“ค๋กœ ์ด๋ฃจ์–ด์ง„ ์ธํ”„๋ผ ๋ชจ๋“ˆ์ž…๋‹ˆ๋‹ค.

๊ฐ„๋‹จํ•œ ์ธํ”„๋ผ ๊ตฌ์„ฑ

๊ตฌ์„ฑ ์š”์†Œ์˜ ๊ตฌ์„ฑ(Composition)๊ณผ ์„ค์ •์˜ ๊ตฌ์„ฑ(Configuration)

์—ญ์ž์˜ ๋ง: ์ด ์ฑ…์—์„œ๋Š” ์–ด๋–ค ๋Œ€์ƒ์„ ์ด๋ฃจ๋Š” ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ง‘ํ•ฉ์„ ์˜๋ฏธํ•˜๋Š” composition๊ณผ ์†Œํ”„ํŠธ์›จ์–ด๋‚˜ ํ™˜๊ฒฝ ๋“ฑ์˜ ์ƒ์„ธ ์˜ต์…˜์„ ์„ค์ •ํ•œ๋‹ค๋Š” ์˜๋ฏธ์˜ configuration์ด๋ผ๋Š” ์šฉ์–ด๊ฐ€ ๋งŽ์ด ์“ฐ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋ง๋กœ ์˜ฎ๊ธฐ๋ฉด ๋‘˜ ๋‹ค '๊ตฌ์„ฑ'์œผ๋กœ ๋ฒˆ์—ญ์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ป๊ฒŒ ํ• ๊นŒ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€, ํ•œ๊ตญ์–ด๋กœ ์ด ์ฑ…์„ ์ ‘ํ•˜์‹œ๋Š” ๋…์ž๋ถ„๋“ค๊ป˜ ๊ฐ€์žฅ ํŽธ์•ˆํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ๋ฐฉ๋ฒ•์ด๊ธฐ๋ฅผ ๋ฐ”๋ผ๋Š” ๋งˆ์Œ์—์„œ '๊ตฌ์„ฑ'์ด๋ผ๊ณ  ์“ฐ๊ณ  ๊ด„ํ˜ธ ์•ˆ์— ์˜์–ด ์›๋ฌธ์˜ ์šฉ์–ด๋ฅผ ๋ณ‘๊ธฐํ•˜๋Š” ๋ฐฉ์‹์„ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ชจ์ชผ๋ก ๋ฒˆ์—ญ์ด ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ผ๋ฉฐ, composition์˜ ๊ตฌ์„ฑ๊ณผ configuration์˜ ๊ตฌ์„ฑ์ด ํ˜ผ๋ž€ ์—†์ด ์ž˜ ์ „๋‹ฌ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ์†Œ์Šค(Data source)

๋ฐ์ดํ„ฐ ์†Œ์Šค๋Š” ์ฝ๊ธฐ ์ „์šฉ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ฉฐ ํ”„๋กœ๋ฐ”์ด๋” ๊ตฌ์„ฑ์— ๋”ฐ๋ผ ๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ ๋ฐ ์ธํ”„๋ผ ๋ชจ๋“ˆ์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ์†Œ์Šค terraform_remote_state๋Š” ์ƒ์œ„ ๋ชจ๋“ˆ ๋ฐ ๊ตฌ์„ฑ(compositions)์— ์ ‘์ฐฉ์ œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ์†Œ์Šค external(์™ธ๋ถ€)๋Š” ์™ธ๋ถ€ ํ”„๋กœ๊ทธ๋žจ์ด ๋ฐ์ดํ„ฐ ์†Œ์Šค ์—ญํ• ์„ ํ•˜์—ฌ, ํ…Œ๋ผํผ ๊ตฌ์„ฑ(configuration)์˜ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ž„์˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋…ธ์ถœ์‹œํ‚ต๋‹ˆ๋‹ค. ์˜ˆ๋กœterraform-aws-lambda module์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ํŒŒ์ผ ์ด๋ฆ„์€ ์™ธ๋ถ€ ํŒŒ์ด์ฌ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ์†Œ์Šค http๋Š” ์ฃผ์–ด์ง„ URL๋กœ HTTP GET ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‚ด๋ณด๋ƒ…๋‹ˆ๋‹ค. ์ด๋Š” ๋„ค์ดํ‹ฐ๋ธŒ Terraform ํ”„๋กœ๋ฐ”์ด๋”๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์—”๋“œํฌ์ธํŠธ์—์„œ ์ •๋ณด๋ฅผ ์–ป๋Š” ๋ฐ ์œ ์šฉํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.

์›๊ฒฉ ์ƒํƒœ(Remote state)

์ธํ”„๋ผ ๋ชจ๋“ˆ ๋ฐ ๊ตฌ์„ฑ(compositions)์€ Terraform state๋ฅผ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๊ฐ€ ์ œ์–ด ๊ฐ€๋Šฅํ•œ ๋ฐฉ์‹(์˜ˆ: ACL ์ง€์ •, ๋ฒ„์ „ ๊ด€๋ฆฌ, ๋กœ๊น…)์œผ๋กœ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š” ์›๊ฒฉ ์œ„์น˜์— ์ง€์†์‹œ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กœํŒŒ์ด๋”(provider), ํ”„๋กœ๋น„์ €๋„ˆ (provisioner) ๋ฐ ๊ธฐํƒ€

ํ”„๋กœํŒŒ์ด๋”, ํ”„๋กœ๋น„์ €๋„ˆ ๋ฐ ๊ธฐํƒ€ ๋ช‡ ๊ฐ€์ง€ ์šฉ์–ด๋Š” ๊ณต์‹ ๋ฌธ์„œ์— ๋งค์šฐ ์ž˜ ์„ค๋ช…๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ ๋ฐ˜๋ณตํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ œ ์ƒ๊ฐ์—๋Š” ์ข‹์€ Terraform ๋ชจ๋“ˆ์„ ์“ฐ๋Š” ๊ฒƒ๊ณผ๋Š” ๊ฑฐ์˜ ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค.

์™œ ์ด๋ ‡๊ฒŒ ์–ด๋ ค์šธ๊นŒ?

๊ฐœ๋ณ„ ๋ฆฌ์†Œ์Šค๋Š” ์ธํ”„๋ผ์˜ ์›์ž์™€ ๊ฐ™์œผ๋ฉฐ ๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ์€ ๋ถ„์ž(์—ฌ๋Ÿฌ ๊ฐœ์˜ ์›์ž๋กœ ๊ตฌ์„ฑ๋จ)์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ชจ๋“ˆ์€ ๋ฒ„์ „์ด ๊ด€๋ฆฌ๋˜๊ณ  ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•œ ๊ฐ€์žฅ ์ž‘์€ ๋‹จ์œ„์ž…๋‹ˆ๋‹ค. ๋ชจ๋“ˆ์—๋Š” ์ •ํ™•ํ•œ ์ธ์ˆ˜ ๋ชฉ๋ก์ด ์žˆ์œผ๋ฉฐ, ํ•ด๋‹น ๋‹จ์œ„๊ฐ€ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ๊ธฐ๋ณธ ๋…ผ๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด terraform-aws-security-group ๋ชจ๋“ˆ์€ ์ž…๋ ฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฆฌ์†Œ์Šค aws_security_group ๋ฐ aws_security_group_rule์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ ์ž์ฒด๋ฅผ ๋‹ค๋ฅธ ๋ชจ๋“ˆ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ์ธํ”„๋ผ ๋ชจ๋“ˆ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ถ„์ž(๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ ๋ฐ ์ธํ”„๋ผ ๋ชจ๋“ˆ) ์ „๋ฐ˜์˜ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๋Š” ๋ชจ๋“ˆ์˜ ์•„์›ƒํ’‹(outputs) ๋ฐ ๋ฐ์ดํ„ฐ ์†Œ์Šค(data sources)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.

๊ตฌ์„ฑ(compositions) ๊ฐ„ ์•ก์„ธ์Šค๋Š” ์›๊ฒฉ ์ƒํƒœ(remote state)์˜ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜ํ–‰๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„์—์„œ ์„ค๋ช…ํ•œ ๊ฐœ๋…์„ ์˜์‚ฌ ์ฝ”๋“œ(pseudo-relations)๋กœ ํ‘œํ˜„ํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

# ํ•œ๊ตญ์–ด
๊ตฌ์„ฑ-1 {
  ์ธํ”„๋ผ-๋ชจ๋“ˆ-1 {
    ๋ฐ์ดํ„ฐ-์†Œ์Šค-1 => d1

    ๋ฆฌ์†Œ์Šค-๋ชจ๋“ˆ-1 {
      ๋ฐ์ดํ„ฐ-์†Œ์Šค2 => d2
      ๋ฆฌ์†Œ์Šค-1 (d1, d2)
      ๋ฆฌ์†Œ์Šค-2 (d2)
    }

    ๋ฆฌ์†Œ์Šค-๋ชจ๋“ˆ-2 {
      ๋ฐ์ดํ„ฐ-์†Œ์Šค-3 => d3
      ๋ฆฌ์†Œ์Šค-3 (d1, d3)
      ๋ฆฌ์†Œ์Šค-4 (d3)
    }
  }
}
# ์˜์–ด(English)
composition-1 {
  infrastructure-module-1 {
    data-source-1 => d1

    resource-module-1 {
      data-source-2 => d2
      resource-1 (d1, d2)
      resource-2 (d2)
    }

    resource-module-2 {
      data-source-3 => d3
      resource-3 (d1, d3)
      resource-4 (d3)
    }
  }
}

์ฝ”๋“œ ๊ตฌ์กฐ

Terraform ์ฝ”๋“œ ๊ตฌ์กฐ์™€ ๊ด€๋ จ๋œ ์งˆ๋ฌธ์€ ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๊ฐ€์žฅ ์ž์ฃผ ๋ฌป๋Š” ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ ๋ชจ๋‘๊ฐ€ ์–ด๋А ์‹œ์ ์—”๊ฐ€ ํ”„๋กœ์ ํŠธ์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์ฝ”๋“œ ๊ตฌ์กฐ๊ฐ€ ๋ฌด์—‡์ผ์ง€ ๊ณ ๋ฏผํ•ด๋ณด๊ธฐ๋„ ํ–ˆ์ฃ .

Terraform ๊ตฌ์„ฑ(configurations)์„ ์–ด๋–ป๊ฒŒ ๊ตฌ์„ฑํ•ด์•ผ ํ• ๊นŒ?

์ด๋Š” ๋งŽ์€ ํ•ด๊ฒฐ์ฑ…์ด ์กด์žฌํ•˜๋Š” ์งˆ๋ฌธ ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ ๋ณดํŽธ์ ์ธ ์กฐ์–ธ์„ ๋“œ๋ฆฌ๊ธฐ๊ฐ€ ๋งค์šฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์šฐ๋ฆฌ๊ฐ€ ๋‹ค๋ฃจ๊ณ ์ž ํ•˜๋Š”๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ์ดํ•ดํ•˜๋Š” ๊ฒƒ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด ๋ด…์‹œ๋‹ค.

  • ํ”„๋กœ์ ํŠธ์˜ ๋ณต์žก์„ฑ์€ ์–ด๋–ป๊ฒŒ ๋˜๋‚˜์š”?

    • ๊ด€๋ จ ๋ฆฌ์†Œ์Šค ์ˆ˜

    • Terraform ํ”„๋กœ๋ฐ”์ด๋” ์ˆ˜(์•„๋ž˜ "๋…ผ๋ฆฌ์  ์ œ๊ณต์ž(logical providers)"์— ๋Œ€ํ•œ ์ฐธ๊ณ  ์‚ฌํ•ญ์„ ํ™•์ธํ•˜์„ธ์š”)

  • ์ธํ”„๋ผ๊ฐ€ ์–ผ๋งˆ๋‚˜ ์ž์ฃผ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๊นŒ?

    • ์›”/์ฃผ/์ผ์— 1ํšŒ๋ถ€ํ„ฐ

    • ์ง€์†์ ์œผ๋กœ๊นŒ์ง€(์ƒˆ ์ปค๋ฐ‹์ด ์žˆ์„ ๋•Œ๋งˆ๋‹ค)

  • ์ฝ”๋“œ ๋ณ€๊ฒฝ ๊ฒŒ์‹œ์ž? ์ƒˆ ์•„ํ‹ฐํŒฉํŠธ๊ฐ€ ๋นŒ๋“œ๋˜๋ฉด CI ์„œ๋ฒ„๊ฐ€ ์ €์žฅ์†Œ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋„๋ก ํ—ˆ์šฉํ•ฉ๋‹ˆ๊นŒ?

    • ๊ฐœ๋ฐœ์ž๋งŒ ์ธํ”„๋ผ ์ €์žฅ์†Œ์— ํ‘ธ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    • ๋ˆ„๊ตฌ๋‚˜ PR์„ ์—ด์–ด ๋ฌด์—‡์— ๋Œ€ํ•œ ๋ณ€๊ฒฝ์ด๋“  ์ œ์•ˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(CI ์„œ๋ฒ„์—์„œ ์‹คํ–‰๋˜๋Š” ์ž๋™ํ™”๋œ ์ž‘์—… ํฌํ•จ).

  • ์–ด๋–ค ๋ฐฐํฌ ํ”Œ๋žซํผ์ด๋‚˜ ๋ฐฐํฌ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜์‹œ๋‚˜์š”?

    • AWS CodeDeploy, Kubernetes ๋˜๋Š”OpenShift์—๋Š” ์•ฝ๊ฐ„ ๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  • ํ™˜๊ฒฝ์€ ์–ด๋–ป๊ฒŒ ๊ทธ๋ฃนํ™”๋˜๋‚˜์š”?

    • ํ™˜๊ฒฝ, ์ง€์—ญ, ํ”„๋กœ์ ํŠธ๋ณ„

๋…ผ๋ฆฌ์  ํ”„๋กœ๋ฐ”์ด๋”๋Š” ์ „์ ์œผ๋กœ Terraform์˜ ๋…ผ๋ฆฌ ๋‚ด์—์„œ ์ž‘๋™ํ•˜๋ฉฐ, ๋‹ค๋ฅธ ์„œ๋น„์Šค์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์œผ๋ฏ€๋กœ ๋ณต์žก์„ฑ์„ O(1)๋กœ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๋…ผ๋ฆฌ์  ํ”„๋กœ๋ฐ”์ด๋”์—๋Š” , , , , ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

Terraform ๊ตฌ์„ฑ(configurations) ๊ตฌ์กฐํ™” ์‹œ์ž‘ํ•˜๊ธฐ

๋ชจ๋“  ์ฝ”๋“œ๋ฅผ main.tf์— ๋„ฃ๋Š” ๊ฒƒ์€ ํ”„๋กœ์ ํŠธ๋ฅผ ๋ง‰ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š” ์ข‹์€ ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒฝ์šฐ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์—ฌ๋Ÿฌ ํŒŒ์ผ์— ๋…ผ๋ฆฌ์ ์œผ๋กœ ๋ถ„ํ• ํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์Šต๋‹ˆ๋‹ค.

  • main.tf - ๋ชจ๋“ˆ, ๋กœ์ปฌ ๋ฐ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค ์ƒ์„ฑ

  • variables.tf - main.tf์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ณ€์ˆ˜ ์„ ์–ธ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค

  • outputs.tf - main.tf์—์„œ ์ƒ์„ฑ๋œ ๋ฆฌ์†Œ์Šค์˜ ์ถœ๋ ฅ(outputs)์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

  • versions.tf - Terraform ๋ฐ ํ”„๋กœ๋ฐ”์ด๋”์— ๋Œ€ํ•œ ๋ฒ„์ „ ์š”๊ตฌ ์‚ฌํ•ญ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

terraform.tfvars๋Š” ์™ธ์—๋Š” ์–ด๋””์—๋„ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

Terraform ๊ตฌ์„ฑ(configuration)์˜ ๊ตฌ์กฐ๋ฅผ ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜๋ฉด ๋ ๊นŒ?

, ๋ฐ ์ด๋‹ค์Œ์˜ ์˜ˆ์—์„œ ์‚ฌ์šฉ๋˜๋‹ˆ ์ด๋“ค์˜ ์ฃผ์š” ๊ฐœ๋…์„ ์ดํ•ดํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

์ฝ”๋“œ ๊ตฌ์กฐํ™”์— ๋Œ€ํ•œ ์ผ๋ฐ˜์ ์ธ ๊ถŒ์žฅ ์‚ฌํ•ญ

  • ์ ์€ ์ˆ˜์˜ ๋ฆฌ์†Œ์Šค๋กœ ์ž‘์—…ํ•˜๋Š” ๊ฒƒ์ด ๋” ์‰ฝ๊ณ  ๋น ๋ฆ…๋‹ˆ๋‹ค.

    • terraform plan ๋ฐ terraform apply๋Š” ๋ชจ๋‘ ํด๋ผ์šฐ๋“œ API ํ˜ธ์ถœ(์˜ˆ: AWS, GCP, Azure)์„ ๋ณด๋‚ด ๋ฆฌ์†Œ์Šค ์ƒํƒœ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    • ์ „์ฒด ์ธํ”„๋ผ๋ฅผ ๋‹จ์ผ ๊ตฌ์„ฑ(composition)์œผ๋กœ ๊ตฌ์„ฑ(configure)ํ•˜๋Š” ๊ฒฝ์šฐ ์‹œ๊ฐ„์ด ๋‹ค์†Œ ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋ฆฌ์†Œ์Šค๊ฐ€ ์ ์„ ๊ฒฝ์šฐ ํญ๋ฐœ ๋ฐ˜๊ฒฝ(์—ญ์ฃผ: blast radius. ๋ณด์•ˆ ์นจํ•ด์˜ ๊ฒฝ์šฐ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์„ ์‹œ ๊ทธ ์—ฌํŒŒ๋กœ ์˜ํ–ฅ์„ ๋ฐ›๋Š” ๋ฒ”์œ„๋ฅผ ํญ๋ฐœ์˜ ๋ฐ˜๊ฒฝ์— ๋น„์œ )์ด ๋” ์ž‘์Šต๋‹ˆ๋‹ค.

    • ๊ด€๋ จ๋˜์ง€ ์•Š์€ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ณ„๋„์˜ ๊ตฌ์„ฑ(composition)์— ๋ฐฐ์น˜ํ•˜์—ฌ ์„œ๋กœ ๊ฒฉ๋ฆฌํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ์œ„ํ—˜์ด ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

  • ์›๊ฒฉ ์ƒํƒœ(remote state)๋ฅผ ์‚ฌ์šฉํ•ด ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•˜์„ธ์š”. ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    • ๋…ธํŠธ๋ถ์€ ์ธํ”„๋ผ์˜ ๋‹จ์ผ ์ง„์‹ค ๊ณต๊ธ‰์›(infrastructure source of truth)์„ ์œ„ํ•œ ์žฅ์†Œ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

    • tfstate ํŒŒ์ผ์„ git์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ํ—ฌ๊ฒŒ์ดํŠธ์˜ ์‹œ์ž‘์ž…๋‹ˆ๋‹ค.

    • ๋‚˜์ค‘์— ์ธํ”„๋ผ ๊ณ„์ธต์ด ์—ฌ๋Ÿฌ ๋ฐฉํ–ฅ(์˜์กด์„ฑdependencies ๋˜๋Š” ๋ฆฌ์†Œ์Šค ์ˆ˜)์œผ๋กœ ์ฆ๊ฐ€ํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด ์ƒํ™ฉ์„ ์ œ์–ดํ•˜๊ธฐ๊ฐ€ ๋” ์‰ฌ์›Œ์งˆ ๊ฒ๋‹ˆ๋‹ค.

  • ์ผ๊ด€๋œ ๊ตฌ์กฐ์™€ ์„ ์‹ค์ฒœํ•˜์„ธ์š”.

    • ์ ˆ์ฐจ์  ์ฝ”๋“œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Terraform ์ฝ”๋“œ๋Š” ๋ฌด์—‡๋ณด๋‹ค ์‚ฌ๋žŒ๋“ค์ด ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ์ž‘์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 6๊ฐœ์›” ํ›„์— ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๋ฐœ์ƒํ•˜๋”๋ผ๋„ ๊ตฌ์กฐ์— ์ผ๊ด€์„ฑ์ด ์žˆ๋‹ค๋ฉด ๋„์›€์ด ๋  ๊ฒ๋‹ˆ๋‹ค.

    • Terraform ์ƒํƒœ ํŒŒ์ผ์—์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ด๋™ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ตฌ์กฐ์™€ ์ด๋ฆ„ ์ง€์ •์ด ์ผ๊ด€๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ด๋™ํ•˜๊ธฐ๊ฐ€ ๋” ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ์„ ์ตœ๋Œ€ํ•œ ๋‹จ์ˆœํ•˜๊ฒŒ ์œ ์ง€ํ•˜์„ธ์š”.

  • ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ• ์ˆ˜ ์žˆ๊ฑฐ๋‚˜ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์€ ํ•˜๋“œ์ฝ”๋”ฉํ•˜์ง€ ๋งˆ์„ธ์š”.

  • ๋ฐ์ดํ„ฐ ์†Œ์Šค์™€ terraform_remote_state๋ฅผ ํŠนํžˆ ๊ตฌ์„ฑ(composition) ๋‚ด ์ธํ”„๋ผ ๋ชจ๋“ˆ ๊ฐ„์˜ ์ ‘์ฐฉ์ œ๋กœ ์‚ฌ์šฉํ•˜์„ธ์š”.

์ด ์ฑ…์—์„œ๋Š” ์˜ˆ์ œ ํ”„๋กœ์ ํŠธ๋“ค์ด ์†Œ๊ทœ๋ชจ ์ธํ”„๋ผ๋ถ€ํ„ฐ ๋Œ€๊ทœ๋ชจ ์ธํ”„๋ผ๊นŒ์ง€ ๋ณต์žก์„ฑ์— ๋”ฐ๋ผ ๊ทธ๋ฃนํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ถ„๋ฆฌ๋Š” ์—„๊ฒฉํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋‹ค๋ฅธ ๊ตฌ์กฐ๋„ ํ™•์ธํ•˜์„ธ์š”.

์ธํ”„๋ผ ๋ชจ๋“ˆ ๋ฐ ๊ตฌ์„ฑ์˜ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜(composition)

์ธํ”„๋ผ๊ฐ€ ์ž‘๋‹ค๋Š” ๊ฒƒ์€ ์˜์กด์„ฑ๋„ ์ ๊ณ  ๋ฆฌ์†Œ์Šค๋„ ์ ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๊ฐ€ ์„ฑ์žฅํ•จ์— ๋”ฐ๋ผ Terraform ๊ตฌ์„ฑ(configurations) ์‹คํ–‰์„ ์—ฐ๊ฒฐํ•˜๊ณ , ๋‹ค์–‘ํ•œ ์ธํ”„๋ผ ๋ชจ๋“ˆ์„ ์—ฐ๊ฒฐํ•˜๊ณ , ๊ตฌ์„ฑ(composition) ๋‚ด์—์„œ ๊ฐ’์„ ์ „๋‹ฌํ•ด์•ผ ํ•  ํ•„์š”์„ฑ์ด ๋ถ„๋ช…ํ•ด์ง‘๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ ์†”๋ฃจ์…˜์—๋Š” ์ตœ์†Œ 5๊ฐ€์ง€ ๊ทธ๋ฃน์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ํ…Œ๋ผํผ๋งŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋Š” ์ž‘์—…์„ ์™„๋ฃŒํ•˜๋ ค๋ฉด Terraform๋งŒ ์•Œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

  2. Terragrunt. ์ „์ฒด ์ธํ”„๋ผ๋ฅผ ์กฐ์œจํ•˜๊ณ  ์˜์กด์„ฑ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ˆœ์ˆ˜ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. Terragrunt๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ธํ”„๋ผ ๋ชจ๋“ˆ ๋ฐ ๊ตฌ์„ฑ(composition)์œผ๋กœ ์ž‘๋™ํ•˜๋ฏ€๋กœ ์ฝ”๋“œ์˜ ์ค‘๋ณต์„ ์ค„์ž…๋‹ˆ๋‹ค.

  3. ์ธํ•˜์šฐ์Šค(in-house) ์Šคํฌ๋ฆฝํŠธ. ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜์„ ์œ„ํ•œ ์ถœ๋ฐœ์ ์œผ๋กœ, ๊ทธ๋ฆฌ๊ณ  Terragrunt๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ธฐ ์ „์— ์‚ฌ์šฉํ•˜๊ณคํ•ฉ๋‹ˆ๋‹ค.

  4. Ansible ๋˜๋Š” ์œ ์‚ฌํ•œ ๋ฒ”์šฉ ์ž๋™ํ™” ๋„๊ตฌ. ์ฃผ๋กœ Ansible ์ดํ›„์— Terraform์„ ์ฑ„ํƒํ•˜๊ฑฐ๋‚˜ Ansible UI๋ฅผ ์ ๊ทน์ ์œผ๋กœ ์‚ฌ์šฉํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

  5. ๋ฐ ๊ธฐํƒ€ Kubernetes์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ ์†”๋ฃจ์…˜. ๋•Œ๋กœ๋Š” Kubernetes ์ƒํƒœ๊ณ„๋ฅผ ํ™œ์šฉํ•˜๊ณ  ์กฐ์ • ๋ฃจํ”„ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด ์›ํ•˜๋Š” Terraform ๊ตฌ์„ฑ(configuration) ์ƒํƒœ๋ฅผ ๋‹ฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋น„๋””์˜ค๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

์ด๋ฅผ ์—ผ๋‘์— ๋‘๊ณ  ์ด ์ฑ…์—์„œ๋Š” ์ด๋Ÿฌํ•œ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ์ค‘ ์ฒ˜์Œ ๋‘ ๊ฐœ, Terraform๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์™€ Terragrunt๋ฅผ ์•Œ์•„๋ด…๋‹ˆ๋‹ค.

๋‹ค์Œ ์žฅ์—์„œ ๋˜๋Š” ์˜ ์ฝ”๋“œ ๊ตฌ์กฐ ์˜ˆ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

Terraform์„ ์‚ฌ์šฉํ•œ ์ค‘๊ฐ„ ๊ทœ๋ชจ ์ธํ”„๋ผ

์ถœ์ฒ˜:

์ด ์˜ˆ์‹œ์—๋Š” ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜๋Š” ์ค‘๊ฐ„ ๊ทœ๋ชจ ์ธํ”„๋ผ์— ๋Œ€ํ•œ Terraform ๊ตฌ์„ฑ(configurations)์„ ๊ตฌ์กฐํ™”ํ•˜๋Š” ์˜ˆ์ œ ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • AWS ๊ณ„์ • 2๊ฐœ

  • 2๊ฐœ์˜ ๋ณ„๋„ ํ™˜๊ฒฝ(์•„๋ฌด๊ฒƒ๋„ ๊ณต์œ ํ•˜์ง€ ์•Š๋Š” prod ๋ฐ stage). ๊ฐ ํ™˜๊ฒฝ์€ ๋ณ„๋„์˜ AWS ๊ณ„์ •์— ์กด์žฌ

  • ๊ฐ ํ™˜๊ฒฝ์€ ์—์„œ ์ œ๊ณต๋˜๋Š” ๊ธฐ์กด ์ธํ”„๋ผ ๋ชจ๋“ˆ(alb)์˜ ๋‹ค๋ฅธ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ๋กœ์ปฌ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ ์†Œ์Šค๋ฅผ ์ œ๊ณตํ•˜๋ฏ€๋กœ ๊ฐ ํ™˜๊ฒฝ์€ ๊ฐ™์€ ๋ฒ„์ „์˜ ๋‚ด๋ถ€ ๋ชจ๋“ˆ modules/network์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ์ธํ”„๋ผ๊ฐ€ ๋…ผ๋ฆฌ์ ์œผ๋กœ ๋ถ„๋ฆฌ๋œ ํ”„๋กœ์ ํŠธ์— ์ ํ•ฉ(๋ณ„๋„์˜ AWS ๊ณ„์ •๋“ค์ด ์“ฐ์ž„)

  • AWS ๊ณ„์ • ๊ฐ„์— ๊ณต์œ ๋œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ(ํ™˜๊ฒฝ 1๊ฐœ = AWS ๊ณ„์ • 1๊ฐœ = ์ƒํƒœ ํŒŒ์ผ 1๊ฐœ)์— ์ข‹์Œ

  • ํ™˜๊ฒฝ ๊ฐ„์— ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์กฐ์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์— ์ ํ•ฉ

  • ์ธํ”„๋ผ๋ฆฌ์†Œ์Šค๊ฐ€ ํ™˜๊ฒฝ๋ณ„๋กœ ์˜๋„์ ์œผ๋กœ ๋‹ฌ๋ผ ์ผ๋ฐ˜ํ™”ํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ(์˜ˆ: ์–ด๋–ค ๋ฆฌ์†Œ์Šค๊ฐ€ ํŠน์ • ํ™˜๊ฒฝ์ด๋‚˜ ์ผ๋ถ€ ์ง€์—ญ์— ์—†์Œ)

ํ”„๋กœ์ ํŠธ๊ฐ€ ์ปค์ง์— ๋”ฐ๋ผ ์ด๋Ÿฌํ•œ ํ™˜๊ฒฝ์„ ์„œ๋กœ ์ตœ์‹  ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์€ ๋”์šฑ ์–ด๋ ค์›Œ์ง‘๋‹ˆ๋‹ค. ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•œ ์ž‘์—…์— ์ธํ”„๋ผ ๋ชจ๋“ˆ(๊ธฐ์กด ๋ชจ๋“ˆ ๋˜๋Š” ๋‚ด๋ถ€ ๋ชจ๋“ˆ) ์‚ฌ์šฉ์„ ๊ณ ๋ คํ•ด ๋ณด์„ธ์š”.

random
local
terraform
null
time
๊ตฌ์„ฑ(composition)
๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ(resource module)
์ธํ”„๋ผ ๋ชจ๋“ˆ(infrastructure module)
๊ตฌ์„ฑ(composition)
๋ช…๋ช… ๊ทœ์น™(naming convention)
Crossplane
Crossplane vs Terraform
Terraform
Terragrunt
https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/medium-terraform
Terraform Registry

Terraform์„ ์‚ฌ์šฉํ•œ ์†Œ๊ทœ๋ชจ ์ธํ”„๋ผ

์ถœ์ฒ˜: https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/small-terraform

์ด ์˜ˆ์‹œ์—๋Š” ์™ธ๋ถ€ ์˜์กด์„ฑ์„ ์ „ํ˜€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์†Œ๊ทœ๋ชจ ์ธํ”„๋ผ์— ๋Œ€ํ•œ Terraform ๊ตฌ์„ฑ(configurations)์„ ๊ตฌ์กฐํ™”ํ•˜๋Š” ์˜ˆ์ œ ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ”„๋กœ์ ํŠธ๋ฅผ์‹œ์ž‘ํ•˜๊ณ  ์ง„ํ–‰ํ•ด ๊ฐ€๋ฉด์„œ ๋ฆฌํŒฉํ† ๋งํ•˜๊ธฐ์— ๋”ฑ์ž…๋‹ˆ๋‹ค.

  • ์†Œ๊ทœ๋ชจ ๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ์— ์ ํ•ฉ

  • ์†Œ๊ทœ๋ชจ ๋ฐ ์„ ํ˜• ์ธํ”„๋ผ ๋ชจ๋“ˆ(์˜ˆ: terraform-aws-atlantis)์— ์ ํ•ฉ

  • ์†Œ์ˆ˜์˜ ๋ฆฌ์†Œ์Šค์— ์ ํ•ฉ(20~30๊ฐœ ๋ฏธ๋งŒ)

๋ฆฌ์†Œ์Šค ์ˆ˜๊ฐ€ ์ฆ๊ฐ€ํ•˜๋Š” ๊ฒฝ์šฐ, ๋ชจ๋“  ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ๋‹จ์ผ ์ƒํƒœ ํŒŒ์ผ์€ Terraform ์ž‘์—… ํ”„๋กœ์„ธ์Šค๋ฅผ ๋А๋ฆฌ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋ฆฌ์†Œ์Šค ์ˆ˜๋ฅผ ์ œํ•œํ•˜๋ ค๋ฉด -target ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค).

Terraform ๊ตฌ์„ฑ(configurations) ์ž‘์„ฑํ•˜๊ธฐ

locals๋ฅผ ์‚ฌ์šฉํ•ด ๋ฆฌ์†Œ์Šค ๊ฐ„์˜ ๋ช…์‹œ์  ์˜์กด์„ฑ ์ง€์ •ํ•˜๊ธฐ

Terraform ๊ตฌ์„ฑ(configurations)์— ์ง์ ‘์ ์ธ ์˜์กด์„ฑ์ด ์—†๋Š” ๊ฒฝ์šฐ์—๋„ ํŠน์ • ๋ฆฌ์†Œ์Šค๊ฐ€ ์‚ญ์ œ๋˜์–ด์•ผ ํ•จ์„ Terraform์— ์•Œ๋ ค์ฃผ๋Š” ์œ ์šฉํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

https://raw.githubusercontent.com/antonbabenko/terraform-best-practices/master/snippets/locals.tf

Terraform 0.12 - ํ•„์ˆ˜์  vs ์„ ํƒ์  ์ธ์ˆ˜

  1. var.website๊ฐ€ ๋นˆ ๋งต์ด ์•„๋‹Œ ๊ฒฝ์šฐ ํ•„์ˆ˜์  ์ธ์ˆ˜ index_document๋ฅผ ๋ฐ˜๋“œ์‹œ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  2. ์„ ํƒ์  ์ธ์ˆ˜ error_document๋Š” ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

main.tf
variable "website" {
  type    = map(string)
  default = {}
}

resource "aws_s3_bucket" "this" {
  # omitted...

  dynamic "website" {
    for_each = length(keys(var.website)) == 0 ? [] : [var.website]

    content {
      index_document = website.value.index_document
      error_document = lookup(website.value, "error_document", null)
    }
  }
}
terraform.tfvars
website = {
  index_document = "index.html"
}

์–ด์„œ์˜ค์„ธ์š”

์ด ๋ฌธ์„œ๋Š” Terraform ์‚ฌ์šฉ์˜ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ์„ค๋ช…ํ•˜๊ณ  Terraform ์‚ฌ์šฉ์ž๋“ค์ด ๊ฒช๋Š” ๊ฐ€์žฅ ํ”ํ•œ ๋ฌธ์ œ์— ๋Œ€ํ•œ ๊ถŒ์žฅ ์‚ฌํ•ญ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์€ ๊ฐ•๋ ฅํ•˜๋ฉฐ(์ง€๊ธˆ ์ตœ๊ฐ•์˜ ํˆด์ด ์•„๋‹ˆ๋ผ๋ฉด) ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ๋„๊ตฌ ์ค‘ ํ•˜๋‚˜๋กœ, ์ธํ”„๋ผ๋ฅผ ์ฝ”๋“œ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋“ค์ด ๋งŽ์€ ์ผ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋ฉฐ ์ง€์›๊ณผ ํ†ตํ•ฉ์„ ์†์‰ฝ๊ฒŒ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

์ด ์ฑ…์—์„œ ์„ค๋ช…ํ•˜๋Š” ์ •๋ณด์˜ ์ผ๋ถ€๋Š” ๋ชจ๋ฒ” ์‚ฌ๋ก€์ฒ˜๋Ÿผ ๋ณด์ด์ง€ ์•Š์„์ง€ ๋ชจ๋ฆ…๋‹ˆ๋‹ค. ์ €๋„ ์ด๋ฅผ ์ธ์ง€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋…์ž๋“ค์ด ์‚ฌ์šฉ์ž๋“ค์ด ์„ ํ˜ธํ•˜๋Š” ๋น„์Šทํ•œ ๋ฐฉ์‹๊ณผ ์—…๊ณ„์—์„œ ํ™•๋ฆฝ๋œ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋„๋ก, ๋ฌธ๋งฅ์— ๋Œ€ํ•œ ํžŒํŠธ์™€ ์•„์ด์ฝ˜์„ ์‚ฌ์šฉํ•ด ๊ฐ ํ•˜์œ„ ํ•ญ๋ชฉ๊ณผ ๊ด€๋ จ๋œ ๋ชจ๋ฒ” ์‚ฌ๋ก€์˜ ๊นŠ์ด๋ฅผ ํ‘œ์‹œํ•ด ๋‘์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ์ฑ…์€ 2018๋…„ ํ–‡์‚ด์ด ๊ฐ€๋“ํ•œ ๋งˆ๋“œ๋ฆฌ๋“œ์—์„œ ์ง‘ํ•„์„ ์‹œ์ž‘ํ–ˆ์œผ๋ฉฐ, ์—ฌ๊ธฐ ์ด ์ฃผ์†Œ์—์„œ ์ฝ์–ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. .

Terraform 1.0์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‹ค์งˆ์  ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ์ง€๋‚œ ๋ช‡ ๋…„ ๊ฐ„ ์—…๋ฐ์ดํŠธํ•ด ์™”์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ์ด ์ฑ…์—๋Š” Terraform ์‚ฌ์šฉ์ž๋“ค์„ ์œ„ํ•œ, ๋…ผ๋ž€์˜ ์—ฌ์ง€๊ฐ€ ์—†๋Š” ๋ชจ๋ฒ” ์‚ฌ๋ก€์™€ ๊ถŒ์žฅ ์‚ฌํ•ญ์ด ๋Œ€๋ถ€๋ถ„ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ›„์›์ž

Please if you want to become a sponsor.

๋ฒˆ์—ญ

์ด ์ฑ…์„ ๋‹ค๋ฅธ ์–ธ์–ด๋กœ ๋ฒˆ์—ญํ•˜๋Š” ๋ฐ ๊ธฐ์—ฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ €์—๊ฒŒ ์—ฐ๋ฝ์ฃผ์„ธ์š”.

๊ธฐ์—ฌ

์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ์„ฑ์ˆ™ํ•ด๊ฐ€๊ณ  ์ƒˆ๋กœ์šด ์•„์ด๋””์–ด๊ฐ€ ๊ตฌํ˜„ ๋ฐ ๊ฒ€์ฆ๋˜์–ด๊ฐ์— ๋”ฐ๋ผ ์ €๋Š” ํ•ญ์ƒ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›์•„ ์ด ์ฑ…์„ ์—…๋ฐ์ดํŠธ ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

ํŠน์ • ์ฃผ์ œ์— ๊ด€์‹ฌ์ด ์žˆ๋‹ค๋ฉด ๋‹ค๋ฃจ์–ด์กŒ์œผ๋ฉด ํ•˜๋Š” ์ด์Šˆ์— ์—„์ง€์†๊ฐ€๋ฝ์„ ๋ˆŒ๋Ÿฌ์ฃผ์„ธ์š”. ๊ธฐ์—ฌํ•˜๊ณ  ์‹ถ์€ ์ฝ˜ํ…์ธ ๋ฅผ ๊ฐ€์ง€๊ณ  ๊ณ„์‹œ๋ฉด ์ดˆ์•ˆ์„ ์ž‘์„ฑํ•ด ํ’€ ๋ฆฌํ€˜์ŠคํŠธ๋ฅผ ์ œ์ถœํ•ด ์ฃผ์„ธ์š”(์ด ๋‹จ๊ณ„์—์„œ๋Š” ๋นผ์–ด๋‚œ ๊ธ€์†œ์”จ๋ฅผ ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค!).

์ €์ž

์ด ์ฑ…์€ ๋‹ค์–‘ํ•œ ๊ธฐ๊ณ ์ž์™€ ๋ฒˆ์—ญ๊ฐ€์˜ ๋„์›€์„ ๋ฐ›์•„ ๊ฐ€ ์œ ์ง€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํŠนํ—ˆ(๋ผ์ด์„ ์Šค)

์ด ์ €์ž‘๋ฌผ์€ Apache 2 ๋ผ์ด์„ ์Šค์— ๋”ฐ๋ผ ๋ผ์ด์„ ์Šค๊ฐ€ ๋ถ€์—ฌ๋ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

๋ณธ ์ปจํ…์ธ ์˜ ์ €์ž์™€ ๊ธฐ์—ฌ์ž๋Š” ๋ณธ ์ปจํ…์ธ ์—์„œ ๋ฐœ๊ฒฌ๋˜๋Š” ์ •๋ณด์˜ ์œ ํšจ์„ฑ์„ ๋ณด์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ท€ํ•˜๋Š” ๋ณธ ์ปจํ…์ธ ์—์„œ ์ œ๊ณต๋˜๋Š” ์ •๋ณด๋Š” ์ž์œ ๋กญ๊ฒŒ ์ œ๊ณต๋˜๋ฉฐ, ๊ท€ํ•˜์™€ ๋ณธ ์ปจํ…์ธ  ๋˜๋Š” ํ”„๋กœ์ ํŠธ์™€ ๊ด€๋ จ๋œ ์‚ฌ๋žŒ๋“ค ์‚ฌ์ด์— ๊ทธ ์–ด๋–ค ์ข…๋ฅ˜์˜ ํ•ฉ์˜๋‚˜ ๊ณ„์•ฝ๋„ ์ด๋ฃจ์–ด์ง€์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์„ ์ดํ•ดํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋ฅ˜ ๋˜๋Š” ๋ˆ„๋ฝ์ด ๊ณผ์‹ค, ์‚ฌ๊ณ  ๋˜๋Š” ์–ด๋–ค ๊ธฐํƒ€ ์›์ธ์— ์˜ํ•œ ๊ฒƒ์ด๋“ , ๋ณธ์ €์ž์™€ ๊ธฐ์—ฌ์ž๋Š” ์ปจํ…์ธ ์— ํฌํ•จ๋˜๊ฑฐ๋‚˜, ๊ด€๋ จ๋˜๊ฑฐ๋‚˜, ์—ฐ๊ฒฐ๋œ ์ •๋ณด์˜ ์˜ค๋ฅ˜ ๋˜๋Š” ๋ˆ„๋ฝ์œผ๋กœ ์ธํ•œ ๊ทธ ์–ด๋– ํ•œ ์†์‹ค, ์†์ƒ ๋˜๋Š” ์ค‘๋‹จ์— ๋Œ€ํ•ด์„œ ๋‹น์‚ฌ์ž์—๊ฒŒ ๊ทธ ์–ด๋– ํ•œ ์ฑ…์ž„๋„ ์ง€์ง€ ์•Š์œผ๋ฉฐ ๊ทธ์ฑ…์ž„์„ ๋ถ€์ธํ•จ์„ ์—ฌ๊ธฐ๋ฐํž™๋‹ˆ๋‹ค.

์ €์ž‘๊ถŒยฉ 2018-2023 ์•ˆ๋˜” ๋ฐ”๋ฒค์ฝ” Anton Babenko.

Terraform์„ ์‚ฌ์šฉํ•œ ๋Œ€๊ทœ๋ชจ ์ธํ”„๋ผ

์ถœ์ฒ˜:

์ด ์˜ˆ์‹œ์—๋Š” ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€๊ทœ๋ชจ ์ธํ”„๋ผ์— ๋Œ€ํ•œ Terraform ๊ตฌ์„ฑ(configurations)์„ ๊ตฌ์กฐํ™”ํ•˜๋Š” ์˜ˆ์ œ ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • AWS ๊ณ„์ • 2๊ฐœ

  • ์ง€์—ญ 2๊ณณ

  • 2๊ฐœ์˜ ๊ฐœ๋ณ„ ํ™˜๊ฒฝ(์•„๋ฌด๊ฒƒ๋„ ๊ณต์œ ํ•˜์ง€ ์•Š๋Š” prod ๋ฐ stag). ๊ฐ ํ™˜๊ฒฝ์€ ๋ณ„๋„์˜ AWS ๊ณ„์ •์— ์กด์žฌํ•˜๋ฉฐ ๋‘ ์ง€์—ญ ๊ฐ„์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ํฌ๊ด„ํ•ฉ๋‹ˆ๋‹ค

  • ๊ฐ ํ™˜๊ฒฝ์€ ์—์„œ ์ œ๊ณต๋˜๋Š” ๊ธฐ์กด ์ธํ”„๋ผ ๋ชจ๋“ˆ(alb)์˜ ๋‹ค๋ฅธ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ๋กœ์ปฌ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ ์†Œ์Šค๋ฅผ ์ œ๊ณตํ•˜๋ฏ€๋กœ ๊ฐ ํ™˜๊ฒฝ์€ ๊ฐ™์€ ๋ฒ„์ „์˜ ๋‚ด๋ถ€ ๋ชจ๋“ˆ modules/network์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์— ์„ค๋ช…๋œ ๊ฒƒ๊ณผ ๊ฐ™์€ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” Terragrrunt๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์ด์ ์ด ๋งค์šฐ ๋ถ„๋ช…ํ•ด์ง‘๋‹ˆ๋‹ค. ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

  • ์ธํ”„๋ผ๊ฐ€๋…ผ๋ฆฌ์ ์œผ๋กœ ๋ถ„๋ฆฌ๋œ ํ”„๋กœ์ ํŠธ์— ์ ํ•ฉ(AWS ๊ณ„์ • ๋ณ„๋„)

  • AWS ๊ณ„์ • ๊ฐ„์— ๊ณต์œ ๋œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ(ํ™˜๊ฒฝ 1๊ฐœ = AWS ๊ณ„์ • 1๊ฐœ = ์ƒํƒœ ํŒŒ์ผ 1๊ฐœ)

  • ํ™˜๊ฒฝ ๊ฐ„์— ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์กฐ์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์— ์ ํ•ฉ

  • ์ธํ”„๋ผ ๋ฆฌ์†Œ์Šค๊ฐ€ ํ™˜๊ฒฝ๋ณ„๋กœ ์˜๋„์ ์œผ๋กœ ๋‹ฌ๋ผ ์ผ๋ฐ˜ํ™”ํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ(์˜ˆ: ์–ด๋–ค ๋ฆฌ์†Œ์Šค๊ฐ€ ํŠน์ • ํ™˜๊ฒฝ์ด๋‚˜ ์ผ๋ถ€ ์ง€์—ญ์— ์—†์Œ)

ํ”„๋กœ์ ํŠธ๊ฐ€ ์ปค์ง์— ๋”ฐ๋ผ ์ด๋Ÿฌํ•œ ํ™˜๊ฒฝ์„ ์„œ๋กœ ์ตœ์‹  ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์€ ๋”์šฑ ์–ด๋ ค์›Œ์ง‘๋‹ˆ๋‹ค. ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•œ ์ž‘์—…์— ์ธํ”„๋ผ ๋ชจ๋“ˆ(๊ธฐ์กด ๋ชจ๋“ˆ ๋˜๋Š” ๋‚ด๋ถ€ ๋ชจ๋“ˆ) ์‚ฌ์šฉ์„ ๊ณ ๋ คํ•ด ๋ณด์„ธ์š”.

FAQ

์ž์ฃผ ๋ฌป๋Š” ํ…Œ๋ผํผ์— ๊ด€ํ•œ ์งˆ๋ฌธ

์ œ๊ฐ€ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•˜๊ณ  ์‚ฌ์šฉ์„ ๊ณ ๋ คํ•ด์•ผ ํ•  ๋„๊ตฌ๋Š” ๋ฌด์—‡์ผ๊นŒ์š”?

  • - ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ ๋„๊ตฌ

  • - ์ฝ”๋“œ ๋ฆฐํ„ฐ

  • - ๋ฒ„์ „ ๊ด€๋ฆฌ์ž

  • - ํ’€ ๋ฆฌํ€˜์ŠคํŠธ ์ž๋™ํ™”

  • - pre-commit ํ”„๋ ˆ์ž„์›Œํฌ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” Terraform์šฉ git ํ›„ํฌ ๋ชจ์Œ

  • - ํ’€ ์š”์ฒญ์—์„œ Terraform์— ๋Œ€ํ•œ ํด๋ผ์šฐ๋“œ ๋น„์šฉ ์ถ”์ •. Terragrunt, Atlantis ๋ฐ pre-commit ํ…Œ๋ผํผ์—์„œ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

๋ฆฌ์†Œ์Šค ๋ฐ ์ธํ”„๋ผ ๋ชจ๋“ˆ์˜ ๋ฒ„์ „์„ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ๋ฐ”์ด๋”๋Š” ๋ชจ๋“ˆ ์™ธ๋ถ€์—์„œ, ํ•˜์ง€๋งŒ ๊ตฌ์„ฑ(composition) ๋‚ด์—์„œ๋งŒ ๊ตฌ์„ฑ๋˜์–ด์•ผ(configure) ํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ๋ฐ”์ด๋” ๋ฐ Terraform ๋ฒ„์ „๋„ ์ž ๊ธ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งˆ์Šคํ„ฐ ์˜์กด์„ฑ ๊ด€๋ฆฌ ๋„๊ตฌ๋Š” ์—†์ง€๋งŒ ์˜์กด์„ฑ ์‚ฌ์–‘๊ณผ ๊ด€๋ จ๋œ ๋ฌธ์ œ๋ฅผ ์ค„์ด๋Š” ๋ช‡ ๊ฐ€์ง€ ํŒ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜์กด์„ฑ ์—…๋ฐ์ดํŠธ๋ฅผ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Dependabot์€ ์˜์กด์„ฑ์„ ์•ˆ์ „ํ•˜๊ฒŒ ์ตœ์‹  ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ํ’€ ๋ฆฌํ€˜์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. Dependabot์€ Terraform ๊ตฌ์„ฑ(configurations)์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/large-terraform
Terraform Registry
Terragrunt๋ฅผ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ ๊ตฌ์กฐ ์˜ˆ์ œ
Terragrunt
tflint
tfenv
Atlantis
pre-commit-terraform
Infracost
์˜์กด์„ฑ ์ง€์˜ฅ
Dependabot

Compliance.tf โ€” Terraform Compliance Simplified. Make your Terraform modules compliance-ready.

โ€”

Terraform
https://www.terraform-best-practices.com/
contact me
์ด์Šˆ๋ฅผ ์—ด๊ฑฐ๋‚˜,
์•ˆ๋˜” ๋ฐ”๋ฒค์ฝ”(Anton Babenko)
๋ผ์ด์„ ์Šค
ุงู„ุนุฑุจูŠุฉ (Arabic)
Bosanski (Bosnian)
Portuguรชs (Brazilian Portuguese)
English
Franรงais (French)
แƒฅแƒแƒ แƒ—แƒฃแƒšแƒ˜ (Georgian)
Deutsch (German)
ฮตฮปฮปฮทฮฝฮนฮบฮฌ (Greek)
ืขื‘ืจื™ืช (Hebrew)
เคนเคฟเค‚เคฆเฅ€ (Hindi)
Bahasa Indonesia (Indonesian)
Italiano (Italian)
ๆ—ฅๆœฌ่ชž (Japanese)
เฒ•เฒจเณเฒจเฒก (Kannada)
Polski (Polish)
Romรขnฤƒ (Romanian)
็ฎ€ไฝ“ไธญๆ–‡ (Simplified Chinese)
Espaรฑol (Spanish)
Tรผrkรงe (Turkish)
ะฃะบั€ะฐั—ะฝััŒะบะฐ (Ukrainian)
ุงุฑุฏูˆ (Urdu)

์ฝ”๋“œ ์Šคํƒ€์ผ๋ง

  • ์˜ˆ์ œ์™€ Terraform ๋ชจ๋“ˆ์—๋Š” ๊ธฐ๋Šฅ ์„ค๋ช…๊ณผ ์‚ฌ์šฉ๋ฒ•์„ ๊ธฐ์ˆ ํ•˜๋Š” ๋ฌธ์„œ๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • README.md ํŒŒ์ผ์˜ ๋ชจ๋“  ๋งํฌ๋Š” Terraform Registry ์›น์‚ฌ์ดํŠธ์—์„œ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ‘œ์‹œ๋˜๋„๋ก ์ ˆ๋Œ€ ๋งํฌ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฌธ์„œ์—๋Š” ๋กœ ๋งŒ๋“  ๋‹ค์ด์–ด๊ทธ๋žจ๊ณผ ๋กœ ๋งŒ๋“  ์ฒญ์‚ฌ์ง„์ด ํฌํ•จ๋˜์–ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • )๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ”๋“œ๊ฐ€ git์— ํ‘ธ์‹œ๋˜๊ณ  ์‚ฌ๋žŒ๋“ค์ด ๊ฒ€ํ† ํ•˜๊ธฐ์— ์•ž์„œ ์ฝ”๋“œ๊ฐ€ ์œ ํšจํ•˜๊ณ , ํ˜•์‹์ด ์ ์ ˆํ•˜๊ณ , ์ž๋™์œผ๋กœ ๋ฌธ์„œํ™”๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

๋ฌธ์„œ

์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ ๋ฌธ์„œ

(์‚ฌ์ „ ์ปค๋ฐ‹)์€ ๋‹ค์ค‘ ์–ธ์–ด ์‚ฌ์ „ ์ปค๋ฐ‹ ํ›„ํฌ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. Python์œผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์œผ๋ฉฐ ์ฝ”๋“œ๊ฐ€ git ์ €์žฅ์†Œ์— ์ปค๋ฐ‹๋˜๊ธฐ์— ์•ž์„œ ๊ฐœ๋ฐœ์ž์˜ ์ปดํ“จํ„ฐ์—์„œ ์ž๋™์œผ๋กœ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฆฐํ„ฐ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์ฝ”๋“œ ํ˜•์‹์„ ์ง€์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค(์ฐธ์กฐ).

Terraform ๊ตฌ์„ฑ(configurations)์„ ์‚ฌ์šฉํ•˜๋ฉด pre-commit(์‚ฌ์ „ ์ปค๋ฐ‹)์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ”๋“œ ํ˜•์‹์„ ์ง€์ •ํ•˜๊ณ  ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•  ์ˆ˜ ์žˆ์„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ฌธ์„œ๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์ „ ์ปค๋ฐ‹์ด ์ต์ˆ™ํ•ด์ง€๋„๋ก ๋ฅผ ํ™•์ธํ•ด๋ณด์„ธ์š”. ๊ทธ๋ฆฌ๊ณ  ์ด ์ €์žฅ์†Œ๊ฐ€ ์ด๋ฏธ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š” ๊ธฐ์กด ์ €์žฅ์†Œ(์˜ˆ: )๋„ ํ™•์ธํ•ด ๋ณด์„ธ์š”.

ํ…Œ๋ผํผ ๋…์Šค(terraform-docs)

(ํ…Œ๋ผํผ ๋…์Šค)๋Š” Terraform ๋ชจ๋“ˆ์—์„œ ๋‹ค์–‘ํ•œ ์ถœ๋ ฅ ํ˜•์‹์œผ๋กœ ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์‚ฌ์ „ ์ปค๋ฐ‹ ํ›„ํฌ ์—†์ด ์ˆ˜๋™์œผ๋กœ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜, (์‚ฌ์ „ ์ปค๋ฐ‹ Terraform ํ›„ํฌ)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์„œ๋ฅผ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@todo: Document module versions, release, GH actions

๋ฆฌ์†Œ์Šค

  1. ๋ธ”๋กœ๊ทธ ๊ธ€:

mermaid
cloudcraft.co
Terraform ์‚ฌ์ „ ์ปค๋ฐ‹ ํ›„ํฌ (Terraform pre-commit hooks
pre-commit
์ง€์›๋˜๋Š” ํ›„ํฌ
pre-commit-terraform ์ €์žฅ์†Œ
terraform-aws-vpc
terraform-docs
pre-commit-terraform hooks
pre-commit ํ”„๋ ˆ์ž„์›Œํฌ ํ™ˆํŽ˜์ด์ง€
pre-commit ํ”„๋ ˆ์ž„์›Œํฌ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” Terraform์šฉ git ํ›„ํฌ ๋ชจ์Œ
Dean Wilson
pre-commit ํ›…๊ณผ terraform - ๋‹น์‹ ์˜ ์ €์žฅ์†Œ๋ฅผ ์œ„ํ•œ ์•ˆ์ „๋ง

๋ช…๋ช… ๊ทœ์น™

์ผ๋ฐ˜์ ์ธ ๊ทœ์น™

์ด ๊ทœ์น™์„ ๋”ฐ๋ฅด์ง€ ์•Š์„ ์ด์œ ๊ฐ€ ์—†์ฃ  :)

์‹ค์ œ ํด๋ผ์šฐ๋“œ ๋ฆฌ์†Œ์Šค์—๋Š” ํ—ˆ์šฉ๋˜๋Š” ์ด๋ฆ„์— ์ œํ•œ์ด ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ผ๋ถ€ ๋ฆฌ์†Œ์Šค์—๋Š” ๋Œ€์‹œ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ์ผ๋ถ€ ๋ฆฌ์†Œ์Šค๋Š” ๋‚™ํƒ€ ํ‘œ๊ธฐ๋ฒ•(CamelCase)์œผ๋กœ ํ‘œ๊ธฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ฑ…์˜ ๊ทœ์น™์€ Terraform ์ด๋ฆ„ ์ž์ฒด๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  1. ๋ฆฌ์†Œ์Šค ์ด๋ฆ„, ๋ฐ์ดํ„ฐ ์†Œ์Šค ์ด๋ฆ„, ๋ณ€์ˆ˜ ์ด๋ฆ„, ์ถœ๋ ฅ ๋“ฑ ๋ชจ๋“  ๊ณณ์—์„œ -(๋Œ€์‹œ, dash) ๋Œ€์‹  _(๋ฐ‘์ค„)์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  2. (UTF-8์ด ์ง€์›๋˜๋”๋ผ๋„) ์†Œ๋ฌธ์ž์™€ ์ˆซ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋ฆฌ์†Œ์Šค ๋ฐ ๋ฐ์ดํ„ฐ ์†Œ์Šค ์ธ์ˆ˜

  1. (์ด๋ฆ„ ์ผ๋ถ€ ๋˜๋Š” ์ „์ฒด๋ฅผ ํฌํ•จํ•ด) ๋ฆฌ์†Œ์Šค ์ด๋ฆ„์— ๋ฆฌ์†Œ์Šค ์œ ํ˜•์„ ๋ฐ˜๋ณตํ•˜์ง€ ๋งˆ์„ธ์š”.

`resource "aws_route_table" "public" {}`
`resource "aws_route_table" "public_route_table" {}`
`resource "aws_route_table" "public_aws_route_table" {}`
  1. ๋ณด๋‹ค ๋” ์„ค๋ช…์ ์ด๊ณ  ์ผ๋ฐ˜์ ์ธ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฑฐ๋‚˜ ๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ์ด ํ•ด๋‹น ์œ ํ˜•์— ๋Œ€ํ•ด ๋‹จ ํ•œ ๊ฐœ์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ(์˜ˆ: AWS VPC module์—๋Š” aws_nat_gateway ์œ ํ˜•์˜ ๋ฆฌ์†Œ์Šค ํ•œ ๊ฐœ์™€ aws_route_table ์œ ํ˜•์˜ ๋ฆฌ์†Œ์Šค๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ๋Š” ๊ฒฝ์šฐ์— aws_nat_gateway๋Š” this๋กœ, aws_route_table์€ private, public, database์™€ ๊ฐ™์ด ๋” ์„ค๋ช…์ ์ธ ์ด๋ฆ„์„ ์ง€์–ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  2. ์ด๋ฆ„์—๋Š” ํ•ญ์ƒ ๋‹จ์ˆ˜ ๋ช…์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

  3. ์ธ์ˆ˜ ๊ฐ’ ๋‚ด๋ถ€์™€ ๊ฐ’์ด ์‚ฌ๋žŒ์—๊ฒŒ ๋…ธ์ถœ๋˜๋Š” ๊ณณ(์˜ˆ: RDS ์ธ์Šคํ„ด์Šค์˜ DNS ์ด๋ฆ„ ๋‚ด๋ถ€)์—๋Š” -๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  4. ๋ฆฌ์†Œ์Šค ๋˜๋Š” ๋ฐ์ดํ„ฐ ์†Œ์Šค ๋ธ”๋ก ๋‚ด๋ถ€์— ์ธ์ˆ˜ count / for_each๋ฅผ ๋งจ ์œ„์˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ํฌํ•จํ•˜๊ณ  ๊ทธ ๋’ค๋Š” ์ค„๋ฐ”๊ฟˆ์œผ๋กœ ๊ตฌ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

  5. ๋ฆฌ์†Œ์Šค์—์„œ ์ง€์›ํ•˜๋Š” ๊ฒฝ์šฐ ์ธ์ˆ˜ tags๋ฅผ ๋งˆ์ง€๋ง‰ ์‹ค์ œ ์ธ์ˆ˜๋กœ ํฌํ•จํ•˜๊ณ  ํ•„์š”ํ•œ ๊ฒฝ์šฐ depends_on ๋ฐ lifecycle์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์ด๋“ค ๋ชจ๋‘๋Š” ํ•˜๋‚˜์˜ ๋นˆ ์ค„๋กœ ๊ตฌ๋ถ„๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  6. ์ธ์ˆ˜ count / for_each์— ์กฐ๊ฑด์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” length๋‚˜ ๋‹ค๋ฅธ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  ๋ถˆ(bool) ๊ฐ’์„ ์“ฐ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

resource ์ฝ”๋“œ ์˜ˆ์ œ

count / for_each์˜ ์‚ฌ์šฉ

main.tf
resource "aws_route_table" "public" {
  count = 2

  vpc_id = "vpc-12345678"
  # ... remaining arguments omitted
}

resource "aws_route_table" "private" {
  for_each = toset(["one", "two"])

  vpc_id = "vpc-12345678"
  # ... remaining arguments omitted
}
main.tf
resource "aws_route_table" "public" {
  vpc_id = "vpc-12345678"
  count  = 2

  # ... remaining arguments omitted
}

tags์˜ ๋ฐฐ์น˜

main.tf
resource "aws_nat_gateway" "this" {
  count = 2

  allocation_id = "..."
  subnet_id     = "..."

  tags = {
    Name = "..."
  }

  depends_on = [aws_internet_gateway.this]

  lifecycle {
    create_before_destroy = true
  }
}   
main.tf
resource "aws_nat_gateway" "this" {
  count = 2

  tags = "..."

  depends_on = [aws_internet_gateway.this]

  lifecycle {
    create_before_destroy = true
  }

  allocation_id = "..."
  subnet_id     = "..."
}

count์˜ ์กฐ๊ฑด

outputs.tf
resource "aws_nat_gateway" "that" {    # Best
  count = var.create_public_subnets ? 1 : 0
}

resource "aws_nat_gateway" "this" {    # Good
  count = length(var.public_subnets) > 0 ? 1 : 0
}

๋ณ€์ˆ˜

  1. ๋ฆฌ์†Œ์Šค ๋ชจ๋“ˆ์˜ ๋ฐ”ํ€ด๋ฅผ ๋‹ค์‹œ ๋งŒ๋“ค์ง€ ๋งˆ์„ธ์š”(์—ญ์ฃผ: Don't reinvent the wheel! ์ด๋ฏธ ๋งŒ๋“ค์–ด์ ธ์„œ ์ž˜ ์“ฐ์ด๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ๋‘๊ณ  ๊ตณ์ด ๋น„์Šทํ•œ ์ˆ˜์ค€์˜ ๊ฒƒ์„ ์ƒˆ๋กœ ๋งŒ๋“œ๋Š” ๋ฐ ์—๋„ˆ์ง€๋ฅผ ์Ÿ๋Š” ๊ฒƒ์„ ํ”ผํ•˜๋ผ๋Š” ๋ง). ์ž‘์—… ์ค‘์ธ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ "์ธ์ˆ˜ ์ฐธ์กฐ" ์„น์…˜์— ์ •์˜๋œ ๋Œ€๋กœ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ name, description, ๋ฐ default๊ฐ’์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

  2. ๋ณ€์ˆ˜์˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ์— ๋Œ€ํ•œ ์ง€์›์€ ๋‹ค์†Œ ์ œํ•œ์ ์ž…๋‹ˆ๋‹ค(์˜ˆ: ๋‹ค๋ฅธ ๋ณ€์ˆ˜์— ์•ก์„ธ์Šคํ•˜๊ฑฐ๋‚˜ ์กฐํšŒ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์Œ). ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์ด ๊ธฐ๋Šฅ์€ ์“ธ๋ชจ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์ƒํ™ฉ์— ๋งž์ถฐ ๊ณ„ํšํ•˜์„ธ์š”.

  3. ์œ ํ˜•์ด list(...) ๋˜๋Š” map(...)์ธ ๊ฒฝ์šฐ ๋ณ€์ˆ˜ ์ด๋ฆ„์— ๋ณต์ˆ˜ํ˜•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  4. ๋ณ€์ˆ˜ ๋ธ”๋ก์˜ ํ‚ค ์ˆœ์„œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง€์ •ํ•˜์„ธ์š”: description , type, default, validation

  5. ๋ถ„๋ช…ํ•˜๋‹ค๊ณ  ์ƒ๊ฐ๋˜๋”๋ผ๋„ ํ•ญ์ƒ ๋ชจ๋“  ๋ณ€์ˆ˜์— ๋Œ€ํ•œ description(์„ค๋ช…)์„ ํฌํ•จํ•˜์„ธ์š”(ํ–ฅํ›„ ํ•„์š”ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค).

  6. ๊ฐ ํ‚ค์— ์—„๊ฒฉํ•œ ์ œ์•ฝ์„ ์ ์šฉํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ํ•œ object()์™€ ๊ฐ™์€ ํŠน์ • ์œ ํ˜•๋ณด๋‹ค๋Š” ๊ฐ„๋‹จํ•œ ์œ ํ˜• (number, string, list(...), map(...), any)์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

  7. ์ง€๋„์˜ ๋ชจ๋“  ์š”์†Œ๊ฐ€ ๋™์ผํ•œ ์œ ํ˜•(์˜ˆ: string๋ฌธ์ž์—ด)์ด๊ฑฐ๋‚˜ ํ•ด๋‹น ์œ ํ˜•์œผ๋กœ ๋ณ€ํ™˜๋  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ(์˜ˆ: number ์ˆซ์ž ์œ ํ˜•์„ string ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ) map(map(string))๊ณผ ๊ฐ™์€ ํŠน์ • ์œ ํ˜•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  8. ํŠน์ • ๊นŠ์ด์—์„œ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ์—ฌ๋Ÿฌ ์œ ํ˜•์„ ์ง€์›ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์— ์œ ํ˜• ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด any ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

  9. ๊ฐ’ {}์€ ์ง€๋„์ผ ๋•Œ๋„ ์žˆ๊ณ  ๊ฐ์ฒด์ผ ๋•Œ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ง€๋„๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด tomap(...)์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

์ถœ๋ ฅ(outputs)

๋ชจ๋“ˆ์˜ ๋ฒ”์œ„ ๋ฐ–์—์„œ๋„ ์ถœ๋ ฅ์„ ์ผ๊ด€๋˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“œ์„ธ์š”(์‚ฌ์šฉ์ž๊ฐ€ ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•  ๋•Œ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ’์˜ ์œ ํ˜•๊ณผ ์†์„ฑ์ด ๋ฌด์—‡์ธ์ง€ ๋ช…ํ™•ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค).

  1. ์ถœ๋ ฅ ์ด๋ฆ„์€ ์ž์‹ ์ด ํฌํ•จํ•˜๋Š” ์†์„ฑ์„ ์„ค๋ช…ํ•ด์•ผ ํ•˜๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ ์šฐ๋ฆฌ๊ฐ€์›ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ํ˜•์‹์ด ๋œ ์ž์œ ๋กญ์Šต๋‹ˆ๋‹ค.

  2. ์ถœ๋ ฅ ์ด๋ฆ„์— ์ ํ•ฉํ•œ ๊ตฌ์กฐ๋Š” {name}_{type}_{attribute}์ด๋ฉฐ ๋‹ค์Œ์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.

    1. {name}์€ ํ”„๋กœ๋ฐ”์ด๋” ์ ‘๋‘์‚ฌ๊ฐ€ ์—†๋Š” ๋ฆฌ์†Œ์Šค ๋˜๋Š” ๋ฐ์ดํ„ฐ ์†Œ์Šค ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. aws_subnet์˜ {name}์€ subnet์ด๊ณ , aws_vpc์˜ ๊ฒฝ์šฐ vpc์ž…๋‹ˆ๋‹ค.

    2. {type}์€ ๋ฆฌ์†Œ์Šค ์†Œ์Šค์˜ ์œ ํ˜•์ž…๋‹ˆ๋‹ค.

    3. {attribute}๋Š” ์ถœ๋ ฅ์ด ๋ฐ˜ํ™˜ํ•˜๋Š” ์†์„ฑ์ž…๋‹ˆ๋‹ค.

    4. ์˜ˆ์ œ ๋ณด๊ธฐ.

  3. ์ถœ๋ ฅ์ด ๋ณด๊ฐ„ ํ•จ์ˆ˜ ๋ฐ ์—ฌ๋Ÿฌ ๋ฆฌ์†Œ์Šค๊ฐ€ ํฌํ•จ๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ {name} ๋ฐ {type}์€ ๊ฐ€๋Šฅํ•œ ํ•œ ์ผ๋ฐ˜์ ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(์ ‘๋‘์‚ฌ๋กœ this๋Š” ์ƒ๋žตํ•ด์•ผ ํ•จ). ์˜ˆ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

  4. ๋ฐ˜ํ™˜๋œ ๊ฐ’์ด ๋ฆฌ์ŠคํŠธ์ธ ๊ฒฝ์šฐ ๋ณต์ˆ˜ํ˜• ์ด๋ฆ„์„ ๊ฐ€์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

  5. ๋ถ„๋ช…ํ•˜๋‹ค๊ณ  ์ƒ๊ฐ๋˜๋”๋ผ๋„ ํ•ญ์ƒ ๋ชจ๋“  ๋ณ€์ˆ˜์— ๋Œ€ํ•œ description(์„ค๋ช…)์„ ํฌํ•จํ•˜์„ธ์š”.

  6. ๋ชจ๋“  ๋ชจ๋“ˆ์˜ ๋ชจ๋“  ์œ„์น˜์—์„œ ์ด ์ถœ๋ ฅ์˜ ์‚ฌ์šฉ์„ ์™„์ „ํžˆ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ๋ฉด sensitive ์ธ์ˆ˜๋ฅผ ์„ค์ •ํ•˜์ง€ ๋งˆ์„ธ์š”.

  7. element(concat(...))(0.13 ์ด์ „ ๋ฒ„์ „์˜ ๋ ˆ๊ฑฐ์‹œ ์ ‘๊ทผ ๋ฐฉ์‹)๋ณด๋‹ค try()(Terraform 0.13๋ถ€ํ„ฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅ)๋ฅผ ์“ฐ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

output ์ฝ”๋“œ ์˜ˆ์ œ

๋ณด์•ˆ ๊ทธ๋ฃน์˜ ID๋ฅผ ์ตœ๋Œ€ 1๊ฐœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค

outputs.tf
output "security_group_id" {
  description = "The ID of the security group"
  value       = try(aws_security_group.this[0].id, aws_security_group.name_prefix[0].id, "")
}

๋™์ผํ•œ ์œ ํ˜•์˜ ๋ฆฌ์†Œ์Šค๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ๋Š” ๊ฒฝ์šฐ ์ถœ๋ ฅ ์ด๋ฆ„์—์„œ this๋ฅผ ์ƒ๋žตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

outputs.tf
output "this_security_group_id" {
  description = "The ID of the security group"
  value       = element(concat(coalescelist(aws_security_group.this.*.id, aws_security_group.web.*.id), [""]), 0)
}

๋ฐ˜ํ™˜ ๊ฐ’์ด ๋ฆฌ์ŠคํŠธ์ธ ๊ฒฝ์šฐ ๋ณต์ˆ˜ํ˜• ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

outputs.tf
output "rds_cluster_instance_endpoints" {
  description = "A list of all cluster instance endpoints"
  value       = aws_rds_cluster_instance.this.*.endpoint
}

์ฐธ๊ณ  ์ž๋ฃŒ

Terraform ์ปค๋ฎค๋‹ˆํ‹ฐ์™€ ๊ด€๋ จ๋œ ํ›Œ๋ฅญํ•œ ์ฝ˜ํ…์ธ ๋ฅผ ๋งŒ๋“ค๊ณ  ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์ด ๋งŽ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฌํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ์—ฌ๊ธฐ์— ์ „๋ถ€ ๋‚˜์—ดํ•  ์ตœ์ ์˜ ๋ฐฉ๋ฒ•์œผ๋กœ awesome-terraform๋งŒํ•œ ์†Œ์Šค๊ฐ€ ์—†๋„ค์š”.

https://twitter.com/antonbabenko/lists/terraform-experts - ๋งค์šฐ ์ ๊ทน์ ์œผ๋กœ Terraform์„ ์‚ฌ์šฉํ•ด ์ผ์„ ํ•˜๊ณ  (๋ฌผ์–ด๋ณด๋ฉด) ๋งŽ์€ ๊ฒƒ์„ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์˜ ๋ชฉ๋ก

https://github.com/shuaibiyy/awesome-terraform - HashiCorp์˜ Terraform์— ๋Œ€ํ•œ ์„ ๋ณ„๋œ ๋ฆฌ์†Œ์Šค ๋ชฉ๋ก

http://bit.ly/terraform-youtube - ์•ˆ๋˜” ๋ฐ”๋ฒค์ฝ”์˜ "๋‹น์‹ ์„ ์œ„ํ•œ Terraform ์ฃผ๊ฐ„ ๋ณต์šฉ๋Ÿ‰" YouTube ์ฑ„๋„. ๋ฆฌ๋ทฐ, ์ธํ„ฐ๋ทฐ, Q&A, ๋ผ์ด๋ธŒ ์ฝ”๋”ฉ ๋ฐ Terraform ๊ฟ€ํŒ์„ ์•Œ๋ ค์ฃผ๋Š” ๋ผ์ด๋ธŒ ์ŠคํŠธ๋ฆฌ๋ฐ

https://weekly.tf - Terraform ์ฃผ๊ฐ„ ๋‰ด์Šค๋ ˆํ„ฐ. ์•ˆ๋˜” ๋ฐ”๋ฒค์ฝ”๊ฐ€ ์ œ๊ณตํ•˜๋Š” Terraform ์„ธ๊ณ„์˜ ๋‹ค์–‘ํ•œ ๋‰ด์Šค(ํ”„๋กœ์ ํŠธ, ๊ณต์ง€, ํ† ๋ก )