├── .gitignore ├── LICENSE.txt ├── README.md └── code ├── bash ├── 01-why-terraform │ ├── README.md │ └── setup-webserver.sh ├── 02-intro-to-terraform-syntax │ ├── README.md │ └── run-webserver.sh └── 03-terraform-state │ ├── README.md │ ├── bash-unit-test-example.sh │ └── user-data.sh ├── packer └── 01-why-terraform │ ├── README.md │ └── webserver.json ├── ruby └── 06-terraform-team │ ├── README.md │ └── terraform-test.rb └── terraform ├── 00-preface └── hello-world │ ├── README.md │ └── main.tf ├── 02-intro-to-terraform-syntax ├── one-server │ ├── README.md │ └── main.tf ├── one-webserver-with-vars │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ └── vars.tf ├── one-webserver │ ├── README.md │ └── main.tf └── webserver-cluster │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ └── vars.tf ├── 03-terraform-state └── file-layout-example │ ├── global │ └── s3 │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf │ └── stage │ ├── data-stores │ └── mysql │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf │ └── services │ └── webserver-cluster │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── user-data.sh │ └── vars.tf ├── 04-terraform-module ├── module-example │ ├── modules │ │ └── services │ │ │ └── webserver-cluster │ │ │ ├── README.md │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── user-data.sh │ │ │ └── vars.tf │ ├── prod │ │ ├── data-stores │ │ │ └── mysql │ │ │ │ ├── README.md │ │ │ │ ├── main.tf │ │ │ │ ├── outputs.tf │ │ │ │ └── vars.tf │ │ └── services │ │ │ └── webserver-cluster │ │ │ ├── README.md │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ └── vars.tf │ └── stage │ │ ├── data-stores │ │ └── mysql │ │ │ ├── README.md │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ └── vars.tf │ │ └── services │ │ └── webserver-cluster │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf └── multi-repo-example │ └── live │ ├── prod │ ├── data-stores │ │ └── mysql │ │ │ ├── README.md │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ └── vars.tf │ └── services │ │ └── webserver-cluster │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf │ └── stage │ ├── data-stores │ └── mysql │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf │ └── services │ └── webserver-cluster │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ └── vars.tf ├── 05-tips-and-tricks ├── loops-and-if-statements │ ├── live │ │ ├── global │ │ │ ├── existing-iam-user │ │ │ │ ├── README.md │ │ │ │ └── main.tf │ │ │ ├── one-iam-user │ │ │ │ ├── README.md │ │ │ │ └── main.tf │ │ │ ├── three-iam-users-increment-name │ │ │ │ ├── README.md │ │ │ │ └── main.tf │ │ │ └── three-iam-users-unique-names │ │ │ │ ├── README.md │ │ │ │ ├── main.tf │ │ │ │ ├── outputs.tf │ │ │ │ └── vars.tf │ │ ├── prod │ │ │ ├── data-stores │ │ │ │ └── mysql │ │ │ │ │ ├── README.md │ │ │ │ │ ├── main.tf │ │ │ │ │ ├── outputs.tf │ │ │ │ │ └── vars.tf │ │ │ └── services │ │ │ │ └── webserver-cluster │ │ │ │ ├── README.md │ │ │ │ ├── main.tf │ │ │ │ ├── outputs.tf │ │ │ │ └── vars.tf │ │ └── stage │ │ │ ├── data-stores │ │ │ └── mysql │ │ │ │ ├── README.md │ │ │ │ ├── main.tf │ │ │ │ ├── outputs.tf │ │ │ │ └── vars.tf │ │ │ └── services │ │ │ ├── multiple-ec2-instances │ │ │ ├── README.md │ │ │ ├── main.tf │ │ │ └── vars.tf │ │ │ └── webserver-cluster │ │ │ ├── README.md │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ └── vars.tf │ └── modules │ │ └── services │ │ └── webserver-cluster │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── user-data-new.sh │ │ ├── user-data.sh │ │ └── vars.tf └── zero-downtime-deployment │ ├── live │ ├── prod │ │ ├── data-stores │ │ │ └── mysql │ │ │ │ ├── README.md │ │ │ │ ├── main.tf │ │ │ │ ├── outputs.tf │ │ │ │ └── vars.tf │ │ └── services │ │ │ └── webserver-cluster │ │ │ ├── README.md │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ └── vars.tf │ └── stage │ │ ├── data-stores │ │ └── mysql │ │ │ ├── README.md │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ └── vars.tf │ │ └── services │ │ └── webserver-cluster │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf │ └── modules │ └── services │ └── webserver-cluster │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── user-data.sh │ └── vars.tf └── 06-terraform-team ├── live ├── prod │ ├── data-stores │ │ └── mysql │ │ │ ├── README.md │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ └── vars.tf │ └── services │ │ └── webserver-cluster │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf └── stage │ ├── data-stores │ └── mysql │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf │ └── services │ └── webserver-cluster │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ └── vars.tf └── modules └── services └── webserver-cluster ├── README.md ├── main.tf ├── outputs.tf ├── user-data.sh └── vars.tf /.gitignore: -------------------------------------------------------------------------------- 1 | *.tfstate 2 | *.tfstate.backup 3 | .terraform 4 | *.iml -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Yevgeniy Brikman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform: 구성과 동작 실습 코드 2 | 3 | 이 코드 레포는 *[Terraform: Up and Running](http://www.terraformupandrunning.com)* by 4 | [Yevgeniy Brikman](http://www.ybrikman.com)를 기반으로 한글 번역과 최신 버전(v0.11.11)으로 코드가 수정 되었습니다. 5 | 6 | ## 시작 하기 7 | 모든 코드는 [code](/code) 폴더에 각 언어별(terraform, bash, ruby, etc)로 단원 순서에 맞춰서 정리가 되어 있습니다. 전체 코드들은 테라폼: 설치에서 운영까지 책의 예제를 기반으로 하므로 대부분의 예제들은 [code/terraform folder](/code/terraform)에 정리가 되어 있습니다. 8 | 9 | 코드를 수행 하는 방법이나 설정에 대한 정보에 대해서는 각 단원의 README에 정리가 되어 있지만 보다 자세한 정보를 원할 경우 책*[Terraform: Up and Running](http://www.terraformupandrunning.com)* 을 참조 10 | 11 | ## 추가 정보 12 | *Terraform: Up and Running*의 실습 예제는 아마존 웹 서비스(AWS) 기준으로 작성 되어 있으며 구글 클라우드 플랫폼(GCP) 이나 마이크로소프트 Azure에 대한 실습을 추가적으로 원할 경우 아래의 레포를 참조 하십시오. 13 | https://github.com/mjuenema/Terraform-Up-and-Running-Code-Samples-Translated/. 14 | 15 | 16 | ## 라이센스 17 | 모든 코드들은 MIT 라이센스를 따르고 있습니다. LICENSE.txt를 참조 하십시오. 18 | -------------------------------------------------------------------------------- /code/bash/01-why-terraform/README.md: -------------------------------------------------------------------------------- 1 | # setup-webserver.sh 2 | 3 | This folder contains an example of a Bash script that can be used to install and Apache, PHP, and a sample PHP app 4 | on an Ubuntu server. 5 | 6 | For more info, please see Chapter 1, "Why Terraform", of 7 | *[Terraform: Up and Running](http://www.terraformupandrunning.com)*. 8 | 9 | ## Pre-requisites 10 | 11 | This script should be run on an Ubuntu server. 12 | 13 | ## Quick start 14 | 15 | ``` 16 | ./setup-webserver.sh 17 | ``` -------------------------------------------------------------------------------- /code/bash/01-why-terraform/setup-webserver.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # A script that configures a web server 3 | 4 | set -e 5 | 6 | # Update the apt-get cache 7 | sudo apt-get update 8 | 9 | # Install PHP 10 | sudo apt-get install -y php 11 | 12 | # Install Apache 13 | sudo apt-get install -y apache2 14 | 15 | # Copy the code from the repository 16 | sudo git clone https://github.com/brikis98/php-app.git /var/www/html/app 17 | 18 | # Start Apache 19 | sudo service apache2 start 20 | -------------------------------------------------------------------------------- /code/bash/02-intro-to-terraform-syntax/README.md: -------------------------------------------------------------------------------- 1 | # run-webserver.sh 2 | 3 | This folder contains an example of a Bash script that can be used to start a web server that listens on port 8080 4 | and returns the text "Hello, World" for the URL `/`. 5 | 6 | For more info, please see Chapter 2, "Getting started with Terraform", of 7 | *[Terraform: Up and Running](http://www.terraformupandrunning.com)*. 8 | 9 | ## Pre-requisites 10 | 11 | You must have [busybox](https://busybox.net/) installed on your computer. 12 | 13 | ## Quick start 14 | 15 | ``` 16 | ./run-webserver.sh 17 | curl http://localhost:8080 18 | ``` -------------------------------------------------------------------------------- /code/bash/02-intro-to-terraform-syntax/run-webserver.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Hello, World" > index.html 3 | nohup busybox httpd -f -p 8080 & 4 | -------------------------------------------------------------------------------- /code/bash/03-terraform-state/README.md: -------------------------------------------------------------------------------- 1 | # bash-unit-test-example.sh 2 | 3 | This folder shows how extracting your [User Data 4 | script](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html) into a separate file allows you to write 5 | unit tests for that file. The folder contains a sample `user-data.sh` Bash script, which fires up a web server on port 6 | 8080, plus a simple unit test for it, `bash-unit-test-example.sh`, that runs that server and checks that it works. 7 | 8 | For more info, please see Chapter 3, "How to Manage Terraform State", of 9 | *[Terraform: Up and Running](http://www.terraformupandrunning.com)*. 10 | 11 | ## Pre-requisites 12 | 13 | You must have [busybox](https://busybox.net/) installed on your computer. 14 | 15 | ## Quick start 16 | 17 | ``` 18 | ./bash-unit-test-example.sh 19 | ``` -------------------------------------------------------------------------------- /code/bash/03-terraform-state/bash-unit-test-example.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export db_address=12.34.56.78 4 | export db_port=5555 5 | export server_port=8888 6 | 7 | ./user-data.sh 8 | 9 | output=$(curl "http://localhost:$server_port") 10 | 11 | if [[ $output == *"Hello, World"* ]]; then 12 | echo "Success! Got expected text from server." 13 | else 14 | echo "Error. Did not get back expected text 'Hello, World'." 15 | fi 16 | -------------------------------------------------------------------------------- /code/bash/03-terraform-state/user-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat > index.html <Hello, World 5 |

DB address: ${db_address}

6 |

DB port: ${db_port}

7 | EOF 8 | 9 | nohup busybox httpd -f -p "${server_port}" & 10 | -------------------------------------------------------------------------------- /code/packer/01-why-terraform/README.md: -------------------------------------------------------------------------------- 1 | # Packer example 2 | 3 | This folder shows an example [Packer](https://www.packer.io/) template that can be used to create an [Amazon Machine 4 | Image (AMI)](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html) of an Ubuntu server with Apache, PHP, and 5 | a sample PHP app installed. 6 | 7 | For more info, please see Chapter 1, "Why Terraform", of 8 | *[Terraform: Up and Running](http://www.terraformupandrunning.com)*. 9 | 10 | ## Pre-requisites 11 | 12 | * You must have [Packer](https://www.packer.io/) installed on your computer. 13 | * You must have an [Amazon Web Services (AWS) account](http://aws.amazon.com/). 14 | 15 | ## Quick start 16 | 17 | **Please note that this example will deploy real resources into your AWS account. We have made every effort to ensure 18 | all the resources qualify for the [AWS Free Tier](https://aws.amazon.com/free/), but we are not responsible for any 19 | charges you may incur.** 20 | 21 | Configure your [AWS access 22 | keys](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) as 23 | environment variables: 24 | 25 | ``` 26 | export AWS_ACCESS_KEY_ID=(your access key id) 27 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 28 | ``` 29 | 30 | To build the AMI: 31 | 32 | ``` 33 | packer build webserver.json 34 | ``` -------------------------------------------------------------------------------- /code/packer/01-why-terraform/webserver.json: -------------------------------------------------------------------------------- 1 | { 2 | "builders": [{ 3 | "ami_name": "packer-example", 4 | "instance_type": "t2.micro", 5 | "region": "us-east-1", 6 | "type": "amazon-ebs", 7 | "source_ami": "ami-40d28157", 8 | "ssh_username": "ubuntu" 9 | }], 10 | "provisioners": [{ 11 | "type": "shell", 12 | "inline": [ 13 | "sudo apt-get update", 14 | "sudo apt-get install -y php", 15 | "sudo apt-get install -y apache2", 16 | "sudo git clone https://github.com/brikis98/php-app.git /var/www/html/app" 17 | ] 18 | }] 19 | } -------------------------------------------------------------------------------- /code/ruby/06-terraform-team/README.md: -------------------------------------------------------------------------------- 1 | # Terraform automated test example 2 | 3 | This folder shows an example of how to write automated tests for a web server cluster defined in 4 | [Terraform](https://www.terraform.io/) templates. The folder contains a Ruby script, `terraform-test.rb`, that will 5 | apply your Terraform configurations and then test the web server cluster URL to make sure it returns "Hello, World". 6 | 7 | For more info, please see Chapter 6, "How to use Terraform as a Team", of 8 | *[Terraform: Up and Running](http://www.terraformupandrunning.com)*. 9 | 10 | ## Pre-requisites 11 | 12 | * You must have [Ruby](https://www.ruby-lang.org/) installed on your computer. 13 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 14 | * You must have an [Amazon Web Services (AWS) account](http://aws.amazon.com/). 15 | 16 | ## Quick start 17 | 18 | **Please note that this example will deploy real resources into your AWS account. We have made every effort to ensure 19 | all the resources qualify for the [AWS Free Tier](https://aws.amazon.com/free/), but we are not responsible for any 20 | charges you may incur.** 21 | 22 | Configure your [AWS access 23 | keys](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) as 24 | environment variables: 25 | 26 | ``` 27 | export AWS_ACCESS_KEY_ID=(your access key id) 28 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 29 | ``` 30 | 31 | Deploy a test database of some sort that the web server cluster can connect to. For example, you could deploy the 32 | Terraform configurations under 33 | [code/terraform/06-terraform-team/live/stage/data-stores/mysql](/code/terraform/06-terraform-team/live/stage/data-stores/mysql). 34 | Make sure to note down the AWS region you're deploying into (e.g. `us-east-1`) as well as the S3 bucket name (e.g. 35 | `my-terraform-state`) and key (e.g. `qa/stage/data-stores/mysql/terraform.tfstate`) you use to store the remote state 36 | data of the database. 37 | 38 | To run the Ruby automated test, navigate to a folder that contains the web server cluster templates, such as 39 | [code/terraform/06-terraform-team/live/stage/services/webserver-cluster](/code/terraform/06-terraform-team/live/stage/services/webserver-cluster), 40 | and run the following: 41 | 42 | ``` 43 | ruby \ 44 | ../../../../../../ruby/06-terraform-team/terraform-test.rb \ 45 | us-east-1 \ 46 | my-terraform-state \ 47 | qa/stage/data-stores/mysql/terraform.tfstate 48 | ``` -------------------------------------------------------------------------------- /code/ruby/06-terraform-team/terraform-test.rb: -------------------------------------------------------------------------------- 1 | require 'net/http' 2 | 3 | if ARGV.length != 3 4 | raise 'Invalid args. Usage: terraform-test.rb REGION DB_BUCKET DB_KEY' 5 | end 6 | 7 | vars = { 8 | # A unique (ish) 6-char string: http://stackoverflow.com/a/88341/483528 9 | :cluster_name => (0...6).map { (65 + rand(26)).chr }.join, 10 | :aws_region => ARGV[0], 11 | :db_remote_state_bucket => ARGV[1], 12 | :db_remote_state_key => ARGV[2], 13 | } 14 | vars_string = vars.map{|key, value| "-var '#{key} = \"#{value}\"'"}.join(', ') 15 | 16 | def test_url(url, expected_text, retries) 17 | retries.times do 18 | begin 19 | output = Net::HTTP.get(URI.parse(url)) 20 | puts "Output from #{url}: #{output}" 21 | return 'Success!' if output.include? expected_text 22 | rescue => e 23 | puts "Error from #{url}: #{e}" 24 | end 25 | 26 | puts 'Sleeping for 30 seconds and trying again' 27 | sleep 30 28 | end 29 | 30 | raise "Response didn't contain '#{expected_text}' after #{retries} retries" 31 | end 32 | 33 | begin 34 | puts "Deploying code in #{Dir.pwd}" 35 | puts `terraform get 2>&1` 36 | puts `terraform apply #{vars_string} 2>&1` 37 | 38 | elb_dns_name = `terraform output -no-color elb_dns_name` 39 | puts test_url("http://#{elb_dns_name.strip}/", 'Hello, World', 10) 40 | ensure 41 | puts "Undeploying code in #{Dir.pwd}" 42 | puts `terraform destroy -force #{vars_string} 2>&1` 43 | end 44 | -------------------------------------------------------------------------------- /code/terraform/00-preface/hello-world/README.md: -------------------------------------------------------------------------------- 1 | # 테라폼 "Hello, World" 실습 2 | 3 | 이번 "Hello, World" 실습은 [Terraform](https://www.terraform.io/) 템플릿 예제를 통해 4 | 아마존 웹 서비스 [Amazon Web Services (AWS)](http://aws.amazon.com/)에 단일 서버를 생성하는 실습 입니다. 5 | 6 | 자세한 실습 진행에 관해서는 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적을 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | 18 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 19 | 를 환경 변수로 설정: 20 | 21 | ``` 22 | export AWS_ACCESS_KEY_ID=(your access key id) 23 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 24 | ``` 25 | 26 | 환경 구성 검토: 27 | 28 | ``` 29 | terraform plan 30 | ``` 31 | 32 | 환경 구성(코드 배포): 33 | 34 | ``` 35 | terraform apply 36 | ``` 37 | 38 | 환경 정리: 39 | 40 | ``` 41 | terraform destroy 42 | ``` 43 | -------------------------------------------------------------------------------- /code/terraform/00-preface/hello-world/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_instance" "example" { 6 | ami = "ami-40d28157" 7 | instance_type = "t2.micro" 8 | } 9 | -------------------------------------------------------------------------------- /code/terraform/02-intro-to-terraform-syntax/one-server/README.md: -------------------------------------------------------------------------------- 1 | # 서버 구성 실습 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)을 통해 4 | 단일 서버([EC2](https://aws.amazon.com/ec2/)활용)를 [Amazon Web Services](http://aws.amazon.com/)에 생성하는 실습 입니다. 5 | 6 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제2장, 테라폼 시작하기" 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | 환경 구성 검토: 26 | 27 | ``` 28 | terraform plan 29 | ``` 30 | 31 | 환경 구성(코드 배포): 32 | 33 | ``` 34 | terraform apply 35 | ``` 36 | 37 | 환경 정리: 38 | 39 | ``` 40 | terraform destroy 41 | ``` 42 | -------------------------------------------------------------------------------- /code/terraform/02-intro-to-terraform-syntax/one-server/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_instance" "example" { 6 | ami = "ami-40d28157" 7 | instance_type = "t2.micro" 8 | 9 | tags { 10 | Name = "terraform-example" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/README.md: -------------------------------------------------------------------------------- 1 | # 웹 서버 구성 실습 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/) 을 통해 단일 웹 서버([EC2](https://aws.amazon.com/ec2/))를 [Amazon Web Services](http://aws.amazon.com/)에 생성하는 실습 입니다. 실습 웹 서버는 8080 포트(변수로 정의한)로 오는 `/` URL 요청에 대해 "Hello, World"의 응답을 수행 합니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제2장, 테라폼 시작하기" 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | 12 | ## 시작 하기 13 | 14 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 15 | 16 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 17 | 를 환경 변수로 설정: 18 | 19 | ``` 20 | export AWS_ACCESS_KEY_ID=(your access key id) 21 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 22 | ``` 23 | 24 | 환경 구성 검토: 25 | 26 | ``` 27 | terraform plan 28 | ``` 29 | 30 | 환경 구성(코드 배포): 31 | 32 | ``` 33 | terraform apply 34 | ``` 35 | 36 | `apply` 명령이 완료된 후, 출력 된 공인 IP 서버 주소 값을 아래에 추가하여 http 요청: 37 | 38 | ``` 39 | curl http://(server_public_ip):8080/ 40 | ``` 41 | 42 | 환경 정리: 43 | 44 | ``` 45 | terraform destroy 46 | ``` 47 | -------------------------------------------------------------------------------- /code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.8, < 0.9" 3 | } 4 | 5 | provider "aws" { 6 | region = "us-east-1" 7 | } 8 | 9 | resource "aws_instance" "example" { 10 | ami = "ami-40d28157" 11 | instance_type = "t2.micro" 12 | vpc_security_group_ids = ["${aws_security_group.instance.id}"] 13 | 14 | user_data = <<-EOF 15 | #!/bin/bash 16 | echo "Hello, World" > index.html 17 | nohup busybox httpd -f -p "${var.server_port}" & 18 | EOF 19 | 20 | tags { 21 | Name = "terraform-example" 22 | } 23 | } 24 | 25 | resource "aws_security_group" "instance" { 26 | name = "terraform-example-instance" 27 | 28 | ingress { 29 | from_port = "${var.server_port}" 30 | to_port = "${var.server_port}" 31 | protocol = "tcp" 32 | cidr_blocks = ["0.0.0.0/0"] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/outputs.tf: -------------------------------------------------------------------------------- 1 | output "public_ip" { 2 | value = "${aws_instance.example.public_ip}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/vars.tf: -------------------------------------------------------------------------------- 1 | variable "server_port" { 2 | description = "The port the server will use for HTTP requests" 3 | default = 8080 4 | } 5 | 6 | variable "list_example" { 7 | description = "An example of a list in Terraform" 8 | type = "list" 9 | default = [1, 2, 3] 10 | } 11 | 12 | variable "map_example" { 13 | description = "An example of a map in Terraform" 14 | type = "map" 15 | 16 | default = { 17 | key1 = "value1" 18 | key2 = "value2" 19 | key3 = "value3" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /code/terraform/02-intro-to-terraform-syntax/one-webserver/README.md: -------------------------------------------------------------------------------- 1 | # Web Server Example 2 | 3 | This folder contains an example [Terraform](https://www.terraform.io/) template that deploys a single web server (using 4 | [EC2](https://aws.amazon.com/ec2/)) in an [Amazon Web Services (AWS) account](http://aws.amazon.com/). The web server 5 | listens on port 8080 and returns the text "Hello, World" for the `/` URL. 6 | 7 | For more info, please see Chapter 2, "Getting started with Terraform", of 8 | *[Terraform: Up and Running](http://www.terraformupandrunning.com)*. 9 | 10 | ## Pre-requisites 11 | 12 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 13 | * You must have an [Amazon Web Services (AWS) account](http://aws.amazon.com/). 14 | 15 | ## Quick start 16 | 17 | **Please note that this example will deploy real resources into your AWS account. We have made every effort to ensure 18 | all the resources qualify for the [AWS Free Tier](https://aws.amazon.com/free/), but we are not responsible for any 19 | charges you may incur.** 20 | 21 | Configure your [AWS access 22 | keys](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) as 23 | environment variables: 24 | 25 | ``` 26 | export AWS_ACCESS_KEY_ID=(your access key id) 27 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 28 | ``` 29 | 30 | Validate the templates: 31 | 32 | ``` 33 | terraform plan 34 | ``` 35 | 36 | Deploy the code: 37 | 38 | ``` 39 | terraform apply 40 | ``` 41 | 42 | When the `apply` command completes, it will output the public IP address of the server. To test that IP: 43 | 44 | ``` 45 | curl http://(server_public_ip):8080/ 46 | ``` 47 | 48 | Clean up when you're done: 49 | 50 | ``` 51 | terraform destroy 52 | ``` 53 | -------------------------------------------------------------------------------- /code/terraform/02-intro-to-terraform-syntax/one-webserver/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_instance" "example" { 6 | ami = "ami-40d28157" 7 | instance_type = "t2.micro" 8 | vpc_security_group_ids = ["${aws_security_group.instance.id}"] 9 | 10 | user_data = <<-EOF 11 | #!/bin/bash 12 | echo "Hello, World" > index.html 13 | nohup busybox httpd -f -p 8080 & 14 | EOF 15 | 16 | tags { 17 | Name = "terraform-example" 18 | } 19 | } 20 | 21 | resource "aws_security_group" "instance" { 22 | name = "terraform-example-instance" 23 | 24 | ingress { 25 | from_port = 8080 26 | to_port = 8080 27 | protocol = "tcp" 28 | cidr_blocks = ["0.0.0.0/0"] 29 | } 30 | } 31 | 32 | output "public_ip" { 33 | value = "${aws_instance.example.public_ip}" 34 | } 35 | -------------------------------------------------------------------------------- /code/terraform/02-intro-to-terraform-syntax/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # Web Server Example 2 | 3 | This folder contains example [Terraform](https://www.terraform.io/) templates that deploy a cluster of web servers 4 | (using [EC2](https://aws.amazon.com/ec2/) and [Auto Scaling](https://aws.amazon.com/autoscaling/)) and a load balancer 5 | (using [ELB](https://aws.amazon.com/elasticloadbalancing/)) in an [Amazon Web Services (AWS) 6 | account](http://aws.amazon.com/). The load balancer listens on port 80 and returns the text "Hello, World" for the 7 | `/` URL. 8 | 9 | For more info, please see Chapter 2, "Getting started with Terraform", of 10 | *[Terraform: Up and Running](http://www.terraformupandrunning.com)*. 11 | 12 | ## Pre-requisites 13 | 14 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 15 | * You must have an [Amazon Web Services (AWS) account](http://aws.amazon.com/). 16 | 17 | ## Quick start 18 | 19 | **Please note that this example will deploy real resources into your AWS account. We have made every effort to ensure 20 | all the resources qualify for the [AWS Free Tier](https://aws.amazon.com/free/), but we are not responsible for any 21 | charges you may incur.** 22 | 23 | Configure your [AWS access 24 | keys](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) as 25 | environment variables: 26 | 27 | ``` 28 | export AWS_ACCESS_KEY_ID=(your access key id) 29 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 30 | ``` 31 | 32 | Validate the templates: 33 | 34 | ``` 35 | terraform plan 36 | ``` 37 | 38 | Deploy the code: 39 | 40 | ``` 41 | terraform apply 42 | ``` 43 | 44 | When the `apply` command completes, it will output the DNS name of the load balancer. To test the load balancer: 45 | 46 | ``` 47 | curl http://(elb_dns_name):8080/ 48 | ``` 49 | 50 | Clean up when you're done: 51 | 52 | ``` 53 | terraform destroy 54 | ``` 55 | -------------------------------------------------------------------------------- /code/terraform/02-intro-to-terraform-syntax/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.8, < 0.9" 3 | } 4 | 5 | provider "aws" { 6 | region = "us-east-1" 7 | } 8 | 9 | resource "aws_launch_configuration" "example" { 10 | image_id = "ami-40d28157" 11 | instance_type = "t2.micro" 12 | security_groups = ["${aws_security_group.instance.id}"] 13 | 14 | user_data = <<-EOF 15 | #!/bin/bash 16 | echo "Hello, World" > index.html 17 | nohup busybox httpd -f -p "${var.server_port}" & 18 | EOF 19 | 20 | lifecycle { 21 | create_before_destroy = true 22 | } 23 | } 24 | 25 | resource "aws_autoscaling_group" "example" { 26 | launch_configuration = "${aws_launch_configuration.example.id}" 27 | availability_zones = ["${data.aws_availability_zones.all.names}"] 28 | 29 | load_balancers = ["${aws_elb.example.name}"] 30 | health_check_type = "ELB" 31 | 32 | min_size = 2 33 | max_size = 10 34 | 35 | tag { 36 | key = "Name" 37 | value = "terraform-asg-example" 38 | propagate_at_launch = true 39 | } 40 | } 41 | 42 | resource "aws_security_group" "instance" { 43 | name = "terraform-example-instance" 44 | 45 | ingress { 46 | from_port = "${var.server_port}" 47 | to_port = "${var.server_port}" 48 | protocol = "tcp" 49 | cidr_blocks = ["0.0.0.0/0"] 50 | } 51 | 52 | lifecycle { 53 | create_before_destroy = true 54 | } 55 | } 56 | 57 | data "aws_availability_zones" "all" {} 58 | 59 | resource "aws_elb" "example" { 60 | name = "terraform-asg-example" 61 | availability_zones = ["${data.aws_availability_zones.all.names}"] 62 | security_groups = ["${aws_security_group.elb.id}"] 63 | 64 | listener { 65 | lb_port = 80 66 | lb_protocol = "http" 67 | instance_port = "${var.server_port}" 68 | instance_protocol = "http" 69 | } 70 | 71 | health_check { 72 | healthy_threshold = 2 73 | unhealthy_threshold = 2 74 | timeout = 3 75 | interval = 30 76 | target = "HTTP:${var.server_port}/" 77 | } 78 | } 79 | 80 | resource "aws_security_group" "elb" { 81 | name = "terraform-example-elb" 82 | 83 | ingress { 84 | from_port = 80 85 | to_port = 80 86 | protocol = "tcp" 87 | cidr_blocks = ["0.0.0.0/0"] 88 | } 89 | 90 | egress { 91 | from_port = 0 92 | to_port = 0 93 | protocol = "-1" 94 | cidr_blocks = ["0.0.0.0/0"] 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /code/terraform/02-intro-to-terraform-syntax/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${aws_elb.example.dns_name}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/02-intro-to-terraform-syntax/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "server_port" { 2 | description = "The port the server will use for HTTP requests" 3 | default = 8080 4 | } 5 | -------------------------------------------------------------------------------- /code/terraform/03-terraform-state/file-layout-example/global/s3/README.md: -------------------------------------------------------------------------------- 1 | # 상태 파일 예제 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)을 통해 [S3](https://aws.amazon.com/s3/) 4 | 버켓을 [Amazon Web Services (AWS) account](http://aws.amazon.com/)에 생성한 다음 해당 S3 버킷을 [원격 상태](https://www.terraform.io/docs/state/remote.html)백엔드로 활용하는 실습 입니다. 5 | 6 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제3장, 테라폼 상태 관리" 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | `vars.tf`의 `default` 매개 변수를 통해 S3 버킷 이름을 정의 가능: 26 | 27 | ```hcl 28 | variable "bucket_name" { 29 | description = "The name of the S3 bucket. Must be globally unique." 30 | default = "(YOUR_BUCKET_NAME)" 31 | } 32 | ``` 33 | 34 | 환경 구성 검토: 35 | 36 | ``` 37 | terraform plan 38 | ``` 39 | 40 | 환경 구성(코드 배포): 41 | 42 | ``` 43 | terraform apply 44 | ``` 45 | 46 | S3가 구성된 이후 원격 상태 저장소 구성을 위해 백엔드 연동: 47 | 48 | ``` 49 | terraform { 50 | backend "s3" { 51 | bucket = "(생성한 버킷 이름)" 52 | key = "terraform.tfstate" 53 | region = "us-east-1" 54 | encrypt = true 55 | } 56 | } 57 | ``` 58 | 59 | 백엔드 구성: 60 | 61 | ``` 62 | terraform init 63 | ``` 64 | 65 | 환경 정리: 66 | 67 | ``` 68 | terraform destroy 69 | ``` 70 | -------------------------------------------------------------------------------- /code/terraform/03-terraform-state/file-layout-example/global/s3/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_s3_bucket" "terraform_state" { 6 | bucket = "${var.bucket_name}" 7 | 8 | versioning { 9 | enabled = true 10 | } 11 | 12 | lifecycle { 13 | prevent_destroy = true 14 | } 15 | } 16 | 17 | ## ============================================================================= 18 | ## <3장> 상태 파일 공유하기 19 | ## Note: S3 버킷이 생성된 후에 아래 코드 주석을 해제 하고 terraform init을 수행 20 | ## 백엔드는 채움 참조 구문을 지원하지 않기 때문에 직접 입력 21 | ## dynamodb_table 값은 아래 "상태 파일 잠금" 수행 후 주석 해제 및 init 수행 22 | ## terraform.backend: configuration cannot contain interpolations 23 | ## 참조 - https://www.terraform.io/docs/backends/config.html 24 | ## ============================================================================= 25 | 26 | #terraform { 27 | # backend "s3" { 28 | # bucket = "(생성한 버킷 이름)" 29 | # key = "terraform.tfstate" 30 | # region = "us-east-1" 31 | # encrypt = true 32 | ## dynamodb_table = "(아래에서 생성한 테이블 이름)" 33 | # } 34 | #} 35 | 36 | ## ============================================================================= 37 | ## <3장> 상태 파일 잠금 38 | ## Note: 잠금 설정을 위한 DynamoDB 리소스 생성 39 | ## 위의 상태 파일 공유를 위한 S3 리소스가 생성된 이후에 아래 코드 주석 해제 40 | ## 하고 apply 명령어 수행 41 | ## 참조 - https://www.terraform.io/docs/backends/types/index.html) 42 | ## ============================================================================= 43 | 44 | #resource "aws_dynamodb_table" "terraform_lock" { 45 | ## var.tf 파일에 dynamodb_name에 대한 주석 해제 46 | # name = "${var.dynamodb_name}" 47 | # hash_key = "LockID" 48 | # read_capacity = 1 49 | # write_capacity = 1 50 | 51 | # attribute { 52 | # name = "LockID" 53 | # type = "S" 54 | # } 55 | #} 56 | -------------------------------------------------------------------------------- /code/terraform/03-terraform-state/file-layout-example/global/s3/outputs.tf: -------------------------------------------------------------------------------- 1 | output "s3_bucket_arn" { 2 | value = "${aws_s3_bucket.terraform_state.arn}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/03-terraform-state/file-layout-example/global/s3/vars.tf: -------------------------------------------------------------------------------- 1 | variable "bucket_name" { 2 | description = "The name of the S3 bucket. Must be globally unique." 3 | } 4 | 5 | #variable "dynamodb_name" { 6 | # description = "The name of the Dynamodb table. Must be globally unique in your account." 7 | #} 8 | -------------------------------------------------------------------------------- /code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # RDS를 통한 MySQL 구성 예제 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)을 통해 [RDS](https://aws.amazon.com/rds/)의 MySQL 데이터베이스 엔진을 4 | 구성 하는 실습 입니다. 5 | 6 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제3장, 테라폼 상태 관리" 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | [S3](https://aws.amazon.com/s3/)에 [원격 상태](https://www.terraform.io/docs/state/remote.html)를 저장하기 때문에 26 | main.tf 파일에 [기존에 생성한 버킷](https://github.com/stitchlabio/terraform-up-and-running-code/tree/master/code/terraform/03-terraform-state/file-layout-example/global/s3)으로 변경이 필요하며 상태 파일 잠금까지 함께 실습하고자 할 경우 dynamodb_table도 함께 변경: 27 | 28 | ``` 29 | terraform { 30 | backend "s3" { 31 | bucket = "(생성한 버킷 이름)" 32 | key = "stage/data-stores/mysql/terraform.tfstate" 33 | region = "us-east-1" 34 | encrypt = true 35 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 36 | } 37 | } 38 | ``` 39 | 40 | 환경 갱신(백엔드 구성을 위함): 41 | 42 | ``` 43 | terraform init 44 | ``` 45 | 46 | 환경 구성 검토: 47 | 48 | ``` 49 | terraform plan 50 | ``` 51 | 52 | 환경 구성(코드 배포): 53 | 54 | ``` 55 | terraform apply 56 | ``` 57 | 58 | 환경 정리: 59 | 60 | ``` 61 | terraform destroy 62 | ``` 63 | -------------------------------------------------------------------------------- /code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_db_instance" "example" { 6 | engine = "mysql" 7 | allocated_storage = 10 8 | instance_class = "db.t2.micro" 9 | name = "example_database" 10 | username = "admin" 11 | password = "${var.db_password}" 12 | skip_final_snapshot = true 13 | } 14 | 15 | terraform { 16 | backend "s3" { 17 | bucket = "(생성한 버킷 이름)" 18 | key = "stage/data-stores/mysql/terraform.tfstate" 19 | region = "us-east-1" 20 | encrypt = true 21 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 22 | } 23 | } -------------------------------------------------------------------------------- /code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | output "address" { 2 | value = "${aws_db_instance.example.address}" 3 | } 4 | 5 | output "port" { 6 | value = "${aws_db_instance.example.port}" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_password" { 2 | description = "The password for the database" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 구성 예제 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제3장, 테라폼 상태 관리" 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | * [data-stores/mysql](../../data-stores/mysql) 리소스가 구성 되어 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | `vars.tf` 파일 안에, [앞에서 구성한](../../data-stores/mysql) S3 버킷 이름과 원격에 저장된 MySQL 데이터베이스 상태 파일 이름을 입력: 26 | 27 | ```hcl 28 | variable "db_remote_state_bucket" { 29 | description = "The name of the S3 bucket used for the database's remote state storage" 30 | } 31 | 32 | variable "db_remote_state_key" { 33 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 34 | } 35 | ``` 36 | 37 | 환경 구성 검토: 38 | 39 | ``` 40 | terraform plan 41 | ``` 42 | 43 | 환경 구성(코드 배포): 44 | 45 | ``` 46 | terraform apply 47 | ``` 48 | 49 | 환경 정리: 50 | 51 | ``` 52 | terraform destroy 53 | ``` 54 | -------------------------------------------------------------------------------- /code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_launch_configuration" "example" { 6 | image_id = "ami-40d28157" 7 | instance_type = "t2.micro" 8 | security_groups = ["${aws_security_group.instance.id}"] 9 | user_data = "${data.template_file.user_data.rendered}" 10 | 11 | lifecycle { 12 | create_before_destroy = true 13 | } 14 | } 15 | 16 | data "template_file" "user_data" { 17 | template = "${file("user-data.sh")}" 18 | 19 | vars { 20 | server_port = "${var.server_port}" 21 | db_address = "${data.terraform_remote_state.db.address}" 22 | db_port = "${data.terraform_remote_state.db.port}" 23 | } 24 | } 25 | 26 | resource "aws_autoscaling_group" "example" { 27 | launch_configuration = "${aws_launch_configuration.example.id}" 28 | availability_zones = ["${data.aws_availability_zones.all.names}"] 29 | 30 | load_balancers = ["${aws_elb.example.name}"] 31 | health_check_type = "ELB" 32 | 33 | min_size = 2 34 | max_size = 10 35 | 36 | tag { 37 | key = "Name" 38 | value = "terraform-asg-example" 39 | propagate_at_launch = true 40 | } 41 | } 42 | 43 | resource "aws_security_group" "instance" { 44 | name = "terraform-example-instance" 45 | 46 | ingress { 47 | from_port = "${var.server_port}" 48 | to_port = "${var.server_port}" 49 | protocol = "tcp" 50 | cidr_blocks = ["0.0.0.0/0"] 51 | } 52 | 53 | lifecycle { 54 | create_before_destroy = true 55 | } 56 | } 57 | 58 | data "aws_availability_zones" "all" {} 59 | 60 | resource "aws_elb" "example" { 61 | name = "terraform-asg-example" 62 | availability_zones = ["${data.aws_availability_zones.all.names}"] 63 | security_groups = ["${aws_security_group.elb.id}"] 64 | 65 | listener { 66 | lb_port = 80 67 | lb_protocol = "http" 68 | instance_port = "${var.server_port}" 69 | instance_protocol = "http" 70 | } 71 | 72 | health_check { 73 | healthy_threshold = 2 74 | unhealthy_threshold = 2 75 | timeout = 3 76 | interval = 30 77 | target = "HTTP:${var.server_port}/" 78 | } 79 | } 80 | 81 | resource "aws_security_group" "elb" { 82 | name = "terraform-example-elb" 83 | 84 | ingress { 85 | from_port = 80 86 | to_port = 80 87 | protocol = "tcp" 88 | cidr_blocks = ["0.0.0.0/0"] 89 | } 90 | 91 | egress { 92 | from_port = 0 93 | to_port = 0 94 | protocol = "-1" 95 | cidr_blocks = ["0.0.0.0/0"] 96 | } 97 | } 98 | 99 | data "terraform_remote_state" "db" { 100 | backend = "s3" 101 | 102 | config { 103 | bucket = "${var.db_remote_state_bucket}" 104 | key = "${var.db_remote_state_key}" 105 | region = "us-east-1" 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${aws_elb.example.dns_name}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/user-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat > index.html <Hello, World 5 |

DB address: ${db_address}

6 |

DB port: ${db_port}

7 | EOF 8 | 9 | nohup busybox httpd -f -p "${server_port}" & 10 | -------------------------------------------------------------------------------- /code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "server_port" { 2 | description = "The port the server will use for HTTP requests" 3 | default = 8080 4 | } 5 | 6 | variable "db_remote_state_bucket" { 7 | description = "The name of the S3 bucket used for the database's remote state storage" 8 | } 9 | 10 | variable "db_remote_state_key" { 11 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 12 | } 13 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 모듈 예제 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제4장, 테라폼 모듈"을 참고 하십시오. 6 | 7 | ## 시작 하기 8 | 9 | 모듈은 테라폼 구성 파일의 묶음이며 코드 전체의 여러 곳에서 재사용 가능하다. 10 | [stage/services/webserver-cluster](../../../stage/services-webserver-cluster)와 11 | [prod/services/webserver-cluster](../../../prod/services-webserver-cluster)에서 이 공통된 모듈을 사용하는 예를 확인 할 수 있습니다. 12 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_launch_configuration" "example" { 2 | image_id = "ami-40d28157" 3 | instance_type = "${var.instance_type}" 4 | security_groups = ["${aws_security_group.instance.id}"] 5 | user_data = "${data.template_file.user_data.rendered}" 6 | 7 | lifecycle { 8 | create_before_destroy = true 9 | } 10 | } 11 | 12 | data "template_file" "user_data" { 13 | template = "${file("${path.module}/user-data.sh")}" 14 | 15 | vars { 16 | server_port = "${var.server_port}" 17 | db_address = "${data.terraform_remote_state.db.address}" 18 | db_port = "${data.terraform_remote_state.db.port}" 19 | } 20 | } 21 | 22 | resource "aws_autoscaling_group" "example" { 23 | launch_configuration = "${aws_launch_configuration.example.id}" 24 | availability_zones = ["${data.aws_availability_zones.all.names}"] 25 | load_balancers = ["${aws_elb.example.name}"] 26 | health_check_type = "ELB" 27 | 28 | min_size = "${var.min_size}" 29 | max_size = "${var.max_size}" 30 | 31 | tag { 32 | key = "Name" 33 | value = "${var.cluster_name}" 34 | propagate_at_launch = true 35 | } 36 | } 37 | 38 | resource "aws_security_group" "instance" { 39 | name = "${var.cluster_name}-instance" 40 | 41 | lifecycle { 42 | create_before_destroy = true 43 | } 44 | } 45 | 46 | resource "aws_security_group_rule" "allow_server_http_inbound" { 47 | type = "ingress" 48 | security_group_id = "${aws_security_group.instance.id}" 49 | 50 | from_port = "${var.server_port}" 51 | to_port = "${var.server_port}" 52 | protocol = "tcp" 53 | cidr_blocks = ["0.0.0.0/0"] 54 | } 55 | 56 | data "aws_availability_zones" "all" {} 57 | 58 | resource "aws_elb" "example" { 59 | name = "${var.cluster_name}" 60 | availability_zones = ["${data.aws_availability_zones.all.names}"] 61 | security_groups = ["${aws_security_group.elb.id}"] 62 | 63 | listener { 64 | lb_port = 80 65 | lb_protocol = "http" 66 | instance_port = "${var.server_port}" 67 | instance_protocol = "http" 68 | } 69 | 70 | health_check { 71 | healthy_threshold = 2 72 | unhealthy_threshold = 2 73 | timeout = 3 74 | interval = 30 75 | target = "HTTP:${var.server_port}/" 76 | } 77 | } 78 | 79 | resource "aws_security_group" "elb" { 80 | name = "${var.cluster_name}-elb" 81 | } 82 | 83 | resource "aws_security_group_rule" "allow_http_inbound" { 84 | type = "ingress" 85 | security_group_id = "${aws_security_group.elb.id}" 86 | 87 | from_port = 80 88 | to_port = 80 89 | protocol = "tcp" 90 | cidr_blocks = ["0.0.0.0/0"] 91 | } 92 | 93 | resource "aws_security_group_rule" "allow_all_outbound" { 94 | type = "egress" 95 | security_group_id = "${aws_security_group.elb.id}" 96 | 97 | from_port = 0 98 | to_port = 0 99 | protocol = "-1" 100 | cidr_blocks = ["0.0.0.0/0"] 101 | } 102 | 103 | data "terraform_remote_state" "db" { 104 | backend = "s3" 105 | 106 | config { 107 | bucket = "${var.db_remote_state_bucket}" 108 | key = "${var.db_remote_state_key}" 109 | region = "us-east-1" 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${aws_elb.example.dns_name}" 3 | } 4 | 5 | output "asg_name" { 6 | value = "${aws_autoscaling_group.example.name}" 7 | } 8 | 9 | output "elb_security_group_id" { 10 | value = "${aws_security_group.elb.id}" 11 | } 12 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/user-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat > index.html <Hello, World 5 |

DB address: ${db_address}

6 |

DB port: ${db_port}

7 | EOF 8 | 9 | nohup busybox httpd -f -p "${server_port}" & 10 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "server_port" { 2 | description = "The port the server will use for HTTP requests" 3 | default = 8080 4 | } 5 | 6 | variable "cluster_name" { 7 | description = "The name to use for all the cluster resources" 8 | } 9 | 10 | variable "db_remote_state_bucket" { 11 | description = "The name of the S3 bucket for the database's remote state" 12 | } 13 | 14 | variable "db_remote_state_key" { 15 | description = "The path for the database's remote state in S3" 16 | } 17 | 18 | variable "instance_type" { 19 | description = "The type of EC2 Instances to run (e.g. t2.micro)" 20 | } 21 | 22 | variable "min_size" { 23 | description = "The minimum number of EC2 Instances in the ASG" 24 | } 25 | 26 | variable "max_size" { 27 | description = "The maximum number of EC2 Instances in the ASG" 28 | } 29 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # RDS를 통한 MySQL 구성 예제 (상용 환경) 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)모듈을 통해 [RDS](https://aws.amazon.com/rds/)의 MySQL 데이터베이스 엔진을 4 | 구성 하는 실습 입니다. 5 | 6 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제4장, 테라폼 모듈" 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | [S3](https://aws.amazon.com/s3/)에 [원격 상태](https://www.terraform.io/docs/state/remote.html)를 저장하기 때문에 26 | main.tf 파일에 [기존에 생성한 버킷](https://github.com/stitchlabio/terraform-up-and-running-code/tree/master/code/terraform/03-terraform-state/file-layout-example/global/s3)으로 변경이 필요하며 상태 파일 잠금까지 함께 실습하고자 할 경우 dynamodb_table도 함께 변경: 27 | 28 | ``` 29 | terraform { 30 | backend "s3" { 31 | bucket = "(생성한 버킷 이름)" 32 | key = "prod/data-stores/mysql/terraform.tfstate" 33 | region = "us-east-1" 34 | encrypt = true 35 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 36 | } 37 | } 38 | ``` 39 | 40 | 환경 갱신(백엔드 구성을 위함): 41 | 42 | ``` 43 | terraform init 44 | ``` 45 | 46 | 환경 구성 검토: 47 | 48 | ``` 49 | terraform plan 50 | ``` 51 | 52 | 환경 구성(코드 배포): 53 | 54 | ``` 55 | terraform apply 56 | ``` 57 | 58 | 환경 정리: 59 | 60 | ``` 61 | terraform destroy 62 | ``` 63 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_db_instance" "example" { 6 | engine = "mysql" 7 | allocated_storage = 10 8 | instance_class = "db.t2.micro" 9 | name = "example_database_prod" 10 | username = "admin" 11 | password = "${var.db_password}" 12 | skip_final_snapshot = true 13 | } 14 | 15 | terraform { 16 | backend "s3" { 17 | bucket = "(생성한 버킷 이름)" 18 | key = "prod/data-stores/mysql/terraform.tfstate" 19 | region = "us-east-1" 20 | encrypt = true 21 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | output "address" { 2 | value = "${aws_db_instance.example.address}" 3 | } 4 | 5 | output "port" { 6 | value = "${aws_db_instance.example.port}" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_password" { 2 | description = "The password for the database" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 구성 예제 (상용 환경) 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 이 코드는 테라폼 모듈로 정의된 클러스터와 로드밸런서 [modules/services/webserver-cluster](../../../../../module-example/modules/services/webserver-cluster)를 포함 합니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제4장, 테라폼 모듈"을 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | * [data-stores/mysql](../../data-stores/mysql) 리소스가 구성 되어 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | `vars.tf` 파일 안에, [data-stores/mysql](../../data-stores/mysql)에서 구성한 S3 버킷 이름과 원격에 저장된 MySQL 데이터베이스 상태 파일 이름을 입력: 26 | 27 | ```hcl 28 | variable "db_remote_state_bucket" { 29 | description = "The name of the S3 bucket used for the database's remote state storage" 30 | } 31 | 32 | variable "db_remote_state_key" { 33 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 34 | } 35 | ``` 36 | 37 | 환경 구성 검토: 38 | 39 | ``` 40 | terraform plan 41 | ``` 42 | 43 | 환경 구성(코드 배포): 44 | 45 | ``` 46 | terraform apply 47 | ``` 48 | 49 | 환경 정리: 50 | 51 | ``` 52 | terraform destroy 53 | ``` 54 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | module "webserver_cluster" { 6 | source = "../../../modules/services/webserver-cluster" 7 | 8 | cluster_name = "webservers-prod" 9 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 10 | db_remote_state_key = "${var.db_remote_state_key}" 11 | 12 | instance_type = "m4.large" 13 | min_size = 2 14 | max_size = 10 15 | } 16 | 17 | resource "aws_autoscaling_schedule" "scale_out_during_business_hours" { 18 | scheduled_action_name = "scale-out-during-business-hours" 19 | min_size = 2 20 | max_size = 10 21 | desired_capacity = 10 22 | recurrence = "0 9 * * *" 23 | 24 | autoscaling_group_name = "${module.webserver_cluster.asg_name}" 25 | } 26 | 27 | resource "aws_autoscaling_schedule" "scale_in_at_night" { 28 | scheduled_action_name = "scale-in-at-night" 29 | min_size = 2 30 | max_size = 10 31 | desired_capacity = 2 32 | recurrence = "0 17 * * *" 33 | 34 | autoscaling_group_name = "${module.webserver_cluster.asg_name}" 35 | } 36 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${module.webserver_cluster.elb_dns_name}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_remote_state_bucket" { 2 | description = "The name of the S3 bucket used for the database's remote state storage" 3 | } 4 | 5 | variable "db_remote_state_key" { 6 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # RDS를 통한 MySQL 구성 예제 (스테이징 환경) 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)모듈을 통해 [RDS](https://aws.amazon.com/rds/)의 MySQL 데이터베이스 엔진을 4 | 구성 하는 실습 입니다. 5 | 6 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제4장, 테라폼 모듈" 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | [S3](https://aws.amazon.com/s3/)에 [원격 상태](https://www.terraform.io/docs/state/remote.html)를 저장하기 때문에 26 | main.tf 파일에 [기존에 생성한 버킷](https://github.com/stitchlabio/terraform-up-and-running-code/tree/master/code/terraform/03-terraform-state/file-layout-example/global/s3)으로 변경이 필요하며 상태 파일 잠금까지 함께 실습하고자 할 경우 dynamodb_table도 함께 변경: 27 | 28 | ``` 29 | terraform { 30 | backend "s3" { 31 | bucket = "(생성한 버킷 이름)" 32 | key = "stage/data-stores/mysql/terraform.tfstate" 33 | region = "us-east-1" 34 | encrypt = true 35 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 36 | } 37 | } 38 | ``` 39 | 40 | 환경 갱신(백엔드 구성을 위함): 41 | 42 | ``` 43 | terraform init 44 | ``` 45 | 46 | 환경 구성 검토: 47 | 48 | ``` 49 | terraform plan 50 | ``` 51 | 52 | 환경 구성(코드 배포): 53 | 54 | ``` 55 | terraform apply 56 | ``` 57 | 58 | 환경 정리: 59 | 60 | ``` 61 | terraform destroy 62 | ``` 63 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_db_instance" "example" { 6 | engine = "mysql" 7 | allocated_storage = 10 8 | instance_class = "db.t2.micro" 9 | name = "example_database_stage" 10 | username = "admin" 11 | password = "${var.db_password}" 12 | skip_final_snapshot = true 13 | } 14 | 15 | terraform { 16 | backend "s3" { 17 | bucket = "(생성한 버킷 이름)" 18 | key = "stage/data-stores/mysql/terraform.tfstate" 19 | region = "us-east-1" 20 | encrypt = true 21 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 22 | } 23 | } -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | output "address" { 2 | value = "${aws_db_instance.example.address}" 3 | } 4 | 5 | output "port" { 6 | value = "${aws_db_instance.example.port}" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_password" { 2 | description = "The password for the database" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 구성 예제 (스테이징 환경) 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 이 코드는 테라폼 모듈로 정의된 클러스터와 로드밸런서 [modules/services/webserver-cluster](../../../modules/services/webserver-cluster)를 포함 합니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제4장, 테라폼 모듈"을 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | * [data-stores/mysql](../../data-stores/mysql) 리소스가 구성 되어 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | `vars.tf` 파일 안에, [앞에서 구성한](../../data-stores/mysql) S3 버킷 이름과 원격에 저장된 MySQL 데이터베이스 상태 파일 이름을 입력: 26 | 27 | ```hcl 28 | variable "db_remote_state_bucket" { 29 | description = "The name of the S3 bucket used for the database's remote state storage" 30 | } 31 | 32 | variable "db_remote_state_key" { 33 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 34 | } 35 | ``` 36 | 37 | 환경 구성 검토: 38 | 39 | ``` 40 | terraform plan 41 | ``` 42 | 43 | 환경 구성(코드 배포): 44 | 45 | ``` 46 | terraform apply 47 | ``` 48 | 49 | 환경 정리: 50 | 51 | ``` 52 | terraform destroy 53 | ``` 54 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | module "webserver_cluster" { 6 | source = "../../../modules/services/webserver-cluster" 7 | 8 | cluster_name = "webservers-stage" 9 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 10 | db_remote_state_key = "${var.db_remote_state_key}" 11 | 12 | instance_type = "t2.micro" 13 | min_size = 2 14 | max_size = 2 15 | } 16 | 17 | resource "aws_security_group_rule" "allow_testing_inbound" { 18 | type = "ingress" 19 | security_group_id = "${module.webserver_cluster.elb_security_group_id}" 20 | 21 | from_port = 12345 22 | to_port = 12345 23 | protocol = "tcp" 24 | cidr_blocks = ["0.0.0.0/0"] 25 | } 26 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${module.webserver_cluster.elb_dns_name}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_remote_state_bucket" { 2 | description = "The name of the S3 bucket used for the database's remote state storage" 3 | } 4 | 5 | variable "db_remote_state_key" { 6 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # RDS를 통한 MySQL 구성 예제 (상용 환경) 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)모듈을 통해 [RDS](https://aws.amazon.com/rds/)의 MySQL 데이터베이스 엔진을 4 | 구성 하는 실습 입니다. 5 | 6 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제4장, 테라폼 모듈" 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | [S3](https://aws.amazon.com/s3/)에 [원격 상태](https://www.terraform.io/docs/state/remote.html)를 저장하기 때문에 26 | main.tf 파일에 [기존에 생성한 버킷](https://github.com/stitchlabio/terraform-up-and-running-code/tree/master/code/terraform/03-terraform-state/file-layout-example/global/s3)으로 변경이 필요하며 상태 파일 잠금까지 함께 실습하고자 할 경우 dynamodb_table도 함께 변경: 27 | 28 | ``` 29 | terraform { 30 | backend "s3" { 31 | bucket = "(생성한 버킷 이름)" 32 | key = "live/prod/data-stores/mysql/terraform.tfstate" 33 | region = "us-east-1" 34 | encrypt = true 35 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 36 | } 37 | } 38 | ``` 39 | 40 | 환경 갱신(백엔드 구성을 위함): 41 | 42 | ``` 43 | terraform init 44 | ``` 45 | 46 | 환경 구성 검토: 47 | 48 | ``` 49 | terraform plan 50 | ``` 51 | 52 | 환경 구성(코드 배포): 53 | 54 | ``` 55 | terraform apply 56 | ``` 57 | 58 | 환경 정리: 59 | 60 | ``` 61 | terraform destroy 62 | ``` 63 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_db_instance" "example" { 6 | engine = "mysql" 7 | allocated_storage = 10 8 | instance_class = "db.t2.micro" 9 | name = "example_database_prod" 10 | username = "admin" 11 | password = "${var.db_password}" 12 | skip_final_snapshot = true 13 | } 14 | 15 | terraform { 16 | backend "s3" { 17 | bucket = "(생성한 버킷 이름)" 18 | key = "live/prod/data-stores/mysql/terraform.tfstate" 19 | region = "us-east-1" 20 | encrypt = true 21 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 22 | } 23 | } -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | output "address" { 2 | value = "${aws_db_instance.example.address}" 3 | } 4 | 5 | output "port" { 6 | value = "${aws_db_instance.example.port}" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_password" { 2 | description = "The password for the database" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 구성 예제 (상용 환경) 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 이 코드는 테라폼 모듈로 정의된 클러스터와 로드밸런서 [modules/services/webserver-cluster](../../../../../module-example/modules/services/webserver-cluster)를 포함 합니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제4장, 테라폼 모듈"을 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | * [data-stores/mysql](../../data-stores/mysql) 리소스가 구성 되어 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | `vars.tf` 파일 안에, [앞에서 구성한](../../data-stores/mysql) S3 버킷 이름과 원격에 저장된 MySQL 데이터베이스 상태 파일 이름을 입력: 26 | 27 | ```hcl 28 | variable "db_remote_state_bucket" { 29 | description = "The name of the S3 bucket used for the database's remote state storage" 30 | } 31 | 32 | variable "db_remote_state_key" { 33 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 34 | } 35 | ``` 36 | 37 | 환경 구성 검토: 38 | 39 | ``` 40 | terraform plan 41 | ``` 42 | 43 | 환경 구성(코드 배포): 44 | 45 | ``` 46 | terraform apply 47 | ``` 48 | 49 | 환경 정리: 50 | 51 | ``` 52 | terraform destroy 53 | ``` 54 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | module "webserver_cluster" { 6 | source = "git@github.com:brikis98/terraform-up-and-running-code.git//code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster?ref=v0.0.1" 7 | 8 | cluster_name = "webservers-prod" 9 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 10 | db_remote_state_key = "${var.db_remote_state_key}" 11 | 12 | instance_type = "m4.large" 13 | min_size = 2 14 | max_size = 10 15 | } 16 | 17 | resource "aws_autoscaling_schedule" "scale_out_during_business_hours" { 18 | scheduled_action_name = "scale-out-during-business-hours" 19 | min_size = 2 20 | max_size = 10 21 | desired_capacity = 10 22 | recurrence = "0 9 * * *" 23 | autoscaling_group_name = "${module.webserver_cluster.asg_name}" 24 | } 25 | 26 | resource "aws_autoscaling_schedule" "scale_in_at_night" { 27 | scheduled_action_name = "scale-in-at-night" 28 | min_size = 2 29 | max_size = 10 30 | desired_capacity = 2 31 | recurrence = "0 17 * * *" 32 | autoscaling_group_name = "${module.webserver_cluster.asg_name}" 33 | } 34 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${module.webserver_cluster.elb_dns_name}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_remote_state_bucket" { 2 | description = "The name of the S3 bucket used for the database's remote state storage" 3 | } 4 | 5 | variable "db_remote_state_key" { 6 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # RDS를 통한 MySQL 구성 예제 (스테이징 환경) 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)모듈을 통해 [RDS](https://aws.amazon.com/rds/)의 MySQL 데이터베이스 엔진을 4 | 구성 하는 실습 입니다. 5 | 6 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제4장, 테라폼 모듈" 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | [S3](https://aws.amazon.com/s3/)에 [원격 상태](https://www.terraform.io/docs/state/remote.html)를 저장하기 때문에 26 | main.tf 파일에 [기존에 생성한 버킷](https://github.com/stitchlabio/terraform-up-and-running-code/tree/master/code/terraform/03-terraform-state/file-layout-example/global/s3)으로 변경이 필요하며 상태 파일 잠금까지 함께 실습하고자 할 경우 dynamodb_table도 함께 변경: 27 | 28 | ``` 29 | terraform { 30 | backend "s3" { 31 | bucket = "(생성한 버킷 이름)" 32 | key = "live/stage/data-stores/mysql/terraform.tfstate" 33 | region = "us-east-1" 34 | encrypt = true 35 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 36 | } 37 | } 38 | ``` 39 | 40 | 환경 갱신(백엔드 구성을 위함): 41 | 42 | ``` 43 | terraform init 44 | ``` 45 | 46 | 환경 구성 검토: 47 | 48 | ``` 49 | terraform plan 50 | ``` 51 | 52 | 환경 구성(코드 배포): 53 | 54 | ``` 55 | terraform apply 56 | ``` 57 | 58 | 환경 정리: 59 | 60 | ``` 61 | terraform destroy 62 | ``` 63 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_db_instance" "example" { 6 | engine = "mysql" 7 | allocated_storage = 10 8 | instance_class = "db.t2.micro" 9 | name = "example_database_stage" 10 | username = "admin" 11 | password = "${var.db_password}" 12 | skip_final_snapshot = true 13 | } 14 | 15 | terraform { 16 | backend "s3" { 17 | bucket = "(생성한 버킷 이름)" 18 | key = "live/stage/data-stores/mysql/terraform.tfstate" 19 | region = "us-east-1" 20 | encrypt = true 21 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 22 | } 23 | } -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | output "address" { 2 | value = "${aws_db_instance.example.address}" 3 | } 4 | 5 | output "port" { 6 | value = "${aws_db_instance.example.port}" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_password" { 2 | description = "The password for the database" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 구성 예제 (스테이징 환경) 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제4장, 테라폼 모듈"을 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | * [data-stores/mysql](../../data-stores/mysql) 리소스가 구성 되어 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | `vars.tf` 파일 안에, [앞에서 구성한](../../data-stores/mysql) S3 버킷 이름과 원격에 저장된 MySQL 데이터베이스 상태 파일 이름을 입력: 26 | 27 | ```hcl 28 | variable "db_remote_state_bucket" { 29 | description = "The name of the S3 bucket used for the database's remote state storage" 30 | } 31 | 32 | variable "db_remote_state_key" { 33 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 34 | } 35 | ``` 36 | 37 | 환경 구성 검토: 38 | 39 | ``` 40 | terraform plan 41 | ``` 42 | 43 | 환경 구성(코드 배포): 44 | 45 | ``` 46 | terraform apply 47 | ``` 48 | 49 | 환경 정리: 50 | 51 | ``` 52 | terraform destroy 53 | ``` 54 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | module "webserver_cluster" { 6 | source = "git@github.com:brikis98/terraform-up-and-running-code.git//code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster?ref=v0.0.2" 7 | 8 | cluster_name = "webservers-stage" 9 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 10 | db_remote_state_key = "${var.db_remote_state_key}" 11 | 12 | instance_type = "t2.micro" 13 | min_size = 2 14 | max_size = 2 15 | } 16 | 17 | resource "aws_security_group_rule" "allow_testing_inbound" { 18 | type = "ingress" 19 | security_group_id = "${module.webserver_cluster.elb_security_group_id}" 20 | 21 | from_port = 12345 22 | to_port = 12345 23 | protocol = "tcp" 24 | cidr_blocks = ["0.0.0.0/0"] 25 | } 26 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${module.webserver_cluster.elb_dns_name}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_remote_state_bucket" { 2 | description = "The name of the S3 bucket used for the database's remote state storage" 3 | } 4 | 5 | variable "db_remote_state_key" { 6 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/global/existing-iam-user/README.md: -------------------------------------------------------------------------------- 1 | # 존재하는 IAM 사용자 예제 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)을 통해 [IAM](https://aws.amazon.com/iam/) 사용자를 생성하는 실습 입니다. 기존에 존재 하는 사용자를 불러오기를 통해 테라폼 상태에 연동하는 예제입니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"를 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | 12 | ## 시작 하기 13 | 14 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 15 | 16 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 17 | 를 환경 변수로 설정: 18 | 19 | ``` 20 | export AWS_ACCESS_KEY_ID=(your access key id) 21 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 22 | ``` 23 | 24 | `main.tf` 파일에 기존에 존재하는 IAM 사용자 이름을 입력: 25 | 26 | ```hcl 27 | resource "aws_iam_user" "existing_user" { 28 | name = "(EXISTING_IAM_USER_NAME)" 29 | } 30 | ``` 31 | 32 | 환경 구성 검토: 33 | 34 | ``` 35 | terraform plan 36 | ``` 37 | 38 | 코드를 배포 하면 기존에 사용자가 존재 하기 때문에 애러 발생: 39 | 40 | ``` 41 | terraform apply 42 | (ERROR) 43 | ``` 44 | 45 | `import` 명령어를 수행: 46 | 47 | ``` 48 | terraform import aws_iam_user.existing_user (EXISTING_IAM_USER_NAME) 49 | ``` 50 | 51 | 다시 `plan`과 `apply` 수행: 52 | 53 | ``` 54 | terraform plan 55 | terraform apply 56 | ``` 57 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/global/existing-iam-user/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_iam_user" "existing_user" { 6 | # 실제로 계정에 이미 존재하는 IAM 사용자 이름으로 아래를 변경해야 하며 7 | # terraform import 명령어로 기존 리소스를 테라폼에 추가할 수 있다. 8 | name = "yevgeniy.brikman" 9 | } 10 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/global/one-iam-user/README.md: -------------------------------------------------------------------------------- 1 | # IAM 사용자 예제 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)을 통해 [IAM](https://aws.amazon.com/iam/) 사용자를 생성하는 실습 입니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"를 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | 12 | ## 시작 하기 13 | 14 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 15 | 16 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 17 | 를 환경 변수로 설정: 18 | 19 | ``` 20 | export AWS_ACCESS_KEY_ID=(your access key id) 21 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 22 | ``` 23 | 24 | 환경 구성 검토: 25 | 26 | ``` 27 | terraform plan 28 | ``` 29 | 30 | 환경 구성(코드 배포): 31 | 32 | ``` 33 | terraform apply 34 | ``` 35 | 36 | 환경 정리: 37 | 38 | ``` 39 | terraform destroy 40 | ``` 41 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/global/one-iam-user/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_iam_user" "example" { 6 | name = "neo" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/global/three-iam-users-increment-name/README.md: -------------------------------------------------------------------------------- 1 | # IAM 사용자 예제 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)을 통해 [IAM](https://aws.amazon.com/iam/) 사용자를 생성하는 실습 입니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"를 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | 12 | ## 시작 하기 13 | 14 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 15 | 16 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 17 | 를 환경 변수로 설정: 18 | 19 | ``` 20 | export AWS_ACCESS_KEY_ID=(your access key id) 21 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 22 | ``` 23 | 24 | 환경 구성 검토: 25 | 26 | ``` 27 | terraform plan 28 | ``` 29 | 30 | 환경 구성(코드 배포): 31 | 32 | ``` 33 | terraform apply 34 | ``` 35 | 36 | 환경 정리: 37 | 38 | ``` 39 | terraform destroy 40 | ``` 41 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/global/three-iam-users-increment-name/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_iam_user" "example" { 6 | count = 3 7 | name = "neo.${count.index}" 8 | } 9 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/global/three-iam-users-unique-names/README.md: -------------------------------------------------------------------------------- 1 | # IAM 사용자 예제 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)을 통해 [IAM](https://aws.amazon.com/iam/) 사용자를 생성하는 실습 입니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"를 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | 12 | ## 시작 하기 13 | 14 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 15 | 16 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 17 | 를 환경 변수로 설정: 18 | 19 | ``` 20 | export AWS_ACCESS_KEY_ID=(your access key id) 21 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 22 | ``` 23 | 24 | `vars.tf`파일에 `default` 매개변수 설정을 통해 IAM 사용자 "neo"를 CloudWatch의 전체 권한 혹은 읽기 전용 권한을 부여: 25 | 26 | ```hcl 27 | variable "give_neo_cloudwatch_full_access" { 28 | description = "If true, neo gets full access to CloudWatch" 29 | # Set this parameter to true or false! 30 | # default = true 31 | } 32 | ``` 33 | 34 | 환경 구성 검토: 35 | 36 | ``` 37 | terraform plan 38 | ``` 39 | 40 | 환경 구성(코드 배포): 41 | 42 | ``` 43 | terraform apply 44 | ``` 45 | 46 | 환경 정리: 47 | 48 | ``` 49 | terraform destroy 50 | ``` 51 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/global/three-iam-users-unique-names/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_iam_user" "example" { 6 | count = "${length(var.user_names)}" 7 | name = "${element(var.user_names, count.index)}" 8 | } 9 | 10 | resource "aws_iam_policy" "ec2_read_only" { 11 | name = "ec2-read-only" 12 | policy = "${data.aws_iam_policy_document.ec2_read_only.json}" 13 | } 14 | 15 | data "aws_iam_policy_document" "ec2_read_only" { 16 | statement { 17 | effect = "Allow" 18 | actions = ["ec2:Describe*"] 19 | resources = ["*"] 20 | } 21 | } 22 | 23 | resource "aws_iam_user_policy_attachment" "ec2_access" { 24 | count = "${length(var.user_names)}" 25 | user = "${element(aws_iam_user.example.*.name, count.index)}" 26 | policy_arn = "${aws_iam_policy.ec2_read_only.arn}" 27 | } 28 | 29 | resource "aws_iam_policy" "cloudwatch_read_only" { 30 | name = "cloudwatch-read-only" 31 | policy = "${data.aws_iam_policy_document.cloudwatch_read_only.json}" 32 | } 33 | 34 | data "aws_iam_policy_document" "cloudwatch_read_only" { 35 | statement { 36 | effect = "Allow" 37 | actions = ["cloudwatch:Describe*", "cloudwatch:Get*", "cloudwatch:List*"] 38 | resources = ["*"] 39 | } 40 | } 41 | 42 | resource "aws_iam_policy" "cloudwatch_full_access" { 43 | name = "cloudwatch-full-access" 44 | policy = "${data.aws_iam_policy_document.cloudwatch_full_access.json}" 45 | } 46 | 47 | data "aws_iam_policy_document" "cloudwatch_full_access" { 48 | statement { 49 | effect = "Allow" 50 | actions = ["cloudwatch:*"] 51 | resources = ["*"] 52 | } 53 | } 54 | 55 | resource "aws_iam_user_policy_attachment" "neo_cloudwatch_full_access" { 56 | count = "${var.give_neo_cloudwatch_full_access}" 57 | 58 | user = "${aws_iam_user.example.0.name}" 59 | policy_arn = "${aws_iam_policy.cloudwatch_full_access.arn}" 60 | } 61 | 62 | resource "aws_iam_user_policy_attachment" "neo_cloudwatch_read_only" { 63 | count = "${1 - var.give_neo_cloudwatch_full_access}" 64 | 65 | user = "${aws_iam_user.example.0.name}" 66 | policy_arn = "${aws_iam_policy.cloudwatch_read_only.arn}" 67 | } 68 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/global/three-iam-users-unique-names/outputs.tf: -------------------------------------------------------------------------------- 1 | output "neo_arn" { 2 | value = "${aws_iam_user.example.0.arn}" 3 | } 4 | 5 | output "all_arns" { 6 | value = ["${aws_iam_user.example.*.arn}"] 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/global/three-iam-users-unique-names/vars.tf: -------------------------------------------------------------------------------- 1 | variable "user_names" { 2 | description = "Create IAM users with these names" 3 | type = "list" 4 | default = ["neo", "trinity", "morpheus"] 5 | } 6 | 7 | variable "give_neo_cloudwatch_full_access" { 8 | description = "If true, neo gets full access to CloudWatch" 9 | } 10 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/prod/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # RDS를 통한 MySQL 구성 예제 (상용 환경) 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)모듈을 통해 [RDS](https://aws.amazon.com/rds/)의 MySQL 데이터베이스 엔진을 4 | 구성 하는 실습 입니다. 5 | 6 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"를 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | [S3](https://aws.amazon.com/s3/)에 [원격 상태](https://www.terraform.io/docs/state/remote.html)를 저장하기 때문에 26 | main.tf 파일에 [기존에 생성한 버킷](https://github.com/stitchlabio/terraform-up-and-running-code/tree/master/code/terraform/03-terraform-state/file-layout-example/global/s3)으로 변경이 필요하며 상태 파일 잠금까지 함께 실습하고자 할 경우 dynamodb_table도 함께 변경: 27 | 28 | ``` 29 | terraform { 30 | backend "s3" { 31 | bucket = "(생성한 버킷 이름)" 32 | key = "live/prod/data-stores/mysql/terraform.tfstate" 33 | region = "us-east-1" 34 | encrypt = true 35 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 36 | } 37 | } 38 | ``` 39 | 40 | 환경 갱신(백엔드 구성을 위함): 41 | 42 | ``` 43 | terraform init 44 | ``` 45 | 46 | 환경 구성 검토: 47 | 48 | ``` 49 | terraform plan 50 | ``` 51 | 52 | 환경 구성(코드 배포): 53 | 54 | ``` 55 | terraform apply 56 | ``` 57 | 58 | 환경 정리: 59 | 60 | ``` 61 | terraform destroy 62 | ``` 63 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/prod/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_db_instance" "example" { 6 | engine = "mysql" 7 | allocated_storage = 10 8 | instance_class = "db.t2.micro" 9 | name = "example_database_prod" 10 | username = "admin" 11 | password = "${var.db_password}" 12 | skip_final_snapshot = true 13 | } 14 | 15 | terraform { 16 | backend "s3" { 17 | bucket = "(생성한 버킷 이름)" 18 | key = "live/prod/data-stores/mysql/terraform.tfstate" 19 | region = "us-east-1" 20 | encrypt = true 21 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 22 | } 23 | } -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/prod/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | output "address" { 2 | value = "${aws_db_instance.example.address}" 3 | } 4 | 5 | output "port" { 6 | value = "${aws_db_instance.example.port}" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/prod/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_password" { 2 | description = "The password for the database" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/prod/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 구성 예제 (상용 환경) 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 이 코드는 테라폼 모듈로 정의된 클러스터와 로드밸런서 [modules/services/webserver-cluster](../../../../modules/services/webserver-cluster)를 포함 합니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"를 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | * [data-stores/mysql](../../data-stores/mysql) 리소스가 구성 되어 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | `vars.tf` 파일 안에, [앞에서 구성한](../../data-stores/mysql) S3 버킷 이름과 원격에 저장된 MySQL 데이터베이스 상태 파일 이름을 입력: 26 | 27 | ```hcl 28 | variable "db_remote_state_bucket" { 29 | description = "The name of the S3 bucket used for the database's remote state storage" 30 | } 31 | 32 | variable "db_remote_state_key" { 33 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 34 | } 35 | ``` 36 | 37 | 환경 구성 검토: 38 | 39 | ``` 40 | terraform plan 41 | ``` 42 | 43 | 환경 구성(코드 배포): 44 | 45 | ``` 46 | terraform apply 47 | ``` 48 | 49 | 환경 정리: 50 | 51 | ``` 52 | terraform destroy 53 | ``` 54 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/prod/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | module "webserver_cluster" { 6 | source = "../../../../modules/services/webserver-cluster" 7 | 8 | cluster_name = "webservers-prod" 9 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 10 | db_remote_state_key = "${var.db_remote_state_key}" 11 | 12 | instance_type = "m4.large" 13 | min_size = 2 14 | max_size = 10 15 | enable_autoscaling = true 16 | enable_new_user_data = false 17 | } 18 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/prod/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${module.webserver_cluster.elb_dns_name}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/prod/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_remote_state_bucket" { 2 | description = "The name of the S3 bucket used for the database's remote state storage" 3 | } 4 | 5 | variable "db_remote_state_key" { 6 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/stage/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # RDS를 통한 MySQL 구성 예제 (스테이징 환경) 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)모듈을 통해 [RDS](https://aws.amazon.com/rds/)의 MySQL 데이터베이스 엔진을 4 | 구성 하는 실습 입니다. 5 | 6 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"를 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | [S3](https://aws.amazon.com/s3/)에 [원격 상태](https://www.terraform.io/docs/state/remote.html)를 저장하기 때문에 26 | main.tf 파일에 [기존에 생성한 버킷](https://github.com/stitchlabio/terraform-up-and-running-code/tree/master/code/terraform/03-terraform-state/file-layout-example/global/s3)으로 변경이 필요하며 상태 파일 잠금까지 함께 실습하고자 할 경우 dynamodb_table도 함께 변경: 27 | 28 | ``` 29 | terraform { 30 | backend "s3" { 31 | bucket = "(생성한 버킷 이름)" 32 | key = "live/stage/data-stores/mysql/terraform.tfstate" 33 | region = "us-east-1" 34 | encrypt = true 35 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 36 | } 37 | } 38 | ``` 39 | 40 | 환경 갱신(백엔드 구성을 위함): 41 | 42 | ``` 43 | terraform init 44 | ``` 45 | 46 | 환경 구성 검토: 47 | 48 | ``` 49 | terraform plan 50 | ``` 51 | 52 | 환경 구성(코드 배포): 53 | 54 | ``` 55 | terraform apply 56 | ``` 57 | 58 | 환경 정리: 59 | 60 | ``` 61 | terraform destroy 62 | ``` 63 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/stage/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_db_instance" "example" { 6 | engine = "mysql" 7 | allocated_storage = 10 8 | instance_class = "db.t2.micro" 9 | name = "example_database_stage" 10 | username = "admin" 11 | password = "${var.db_password}" 12 | skip_final_snapshot = true 13 | } 14 | 15 | terraform { 16 | backend "s3" { 17 | bucket = "(생성한 버킷 이름)" 18 | key = "live/stage/data-stores/mysql/terraform.tfstate" 19 | region = "us-east-1" 20 | encrypt = true 21 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 22 | } 23 | } -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/stage/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | output "address" { 2 | value = "${aws_db_instance.example.address}" 3 | } 4 | 5 | output "port" { 6 | value = "${aws_db_instance.example.port}" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/stage/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_password" { 2 | description = "The password for the database" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/stage/services/multiple-ec2-instances/README.md: -------------------------------------------------------------------------------- 1 | # 다중 서버 구성 예제 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/)를 통해 다중 서버를 구성하는 실습 입니다. 이번 실습을 통해서 +count+ 매개변수가 어떻게 동작하고 어떤 주의사항이 있는지 알아보는 실습 입니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"을 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | 12 | ## 시작 하기 13 | 14 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 15 | 16 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 17 | 를 환경 변수로 설정: 18 | 19 | ``` 20 | export AWS_ACCESS_KEY_ID=(your access key id) 21 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 22 | ``` 23 | 24 | `vars.tf` 파일 안에, [앞에서 구성한](../../data-stores/mysql) S3 버킷 이름과 원격에 저장된 MySQL 데이터베이스 상태 파일 이름을 입력: 25 | 26 | 환경 구성 검토: 27 | 28 | ``` 29 | terraform plan 30 | ``` 31 | 32 | 환경 구성(코드 배포): 33 | 34 | ``` 35 | terraform apply 36 | ``` 37 | 38 | 환경 정리: 39 | 40 | ``` 41 | terraform destroy 42 | ``` 43 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/stage/services/multiple-ec2-instances/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | data "aws_availability_zones" "all" {} 6 | 7 | resource "aws_instance" "example" { 8 | count = "${var.num_availability_zones}" 9 | availability_zone = "${element(data.aws_availability_zones.all.names, count.index)}" 10 | 11 | ami = "ami-40d28157" 12 | instance_type = "t2.micro" 13 | } 14 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/stage/services/multiple-ec2-instances/vars.tf: -------------------------------------------------------------------------------- 1 | variable "num_availability_zones" { 2 | description = "The number of Availability Zones in the AWS region" 3 | default = 3 4 | } 5 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/stage/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 구성 예제 (스테이징 환경) 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 자동 스케일링 그룹 설정을 통해서 무중단 배포가 가능 합니다. 클러스터와 로드밸런서 구성을 위해 [modules/services/webserver-cluster](../../../../modules/services/webserver-cluster) 모듈을 포함 하고 있습니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제6장, 테라폼을 팀에서 사용하기"을 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | * [data-stores/mysql](../../data-stores/mysql) 리소스가 구성 되어 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | `vars.tf` 파일 안에, [앞에서 구성한](../../data-stores/mysql) S3 버킷 이름과 원격에 저장된 MySQL 데이터베이스 상태 파일 이름을 입력: 26 | 27 | ```hcl 28 | variable "db_remote_state_bucket" { 29 | description = "The name of the S3 bucket used for the database's remote state storage" 30 | } 31 | 32 | variable "db_remote_state_key" { 33 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 34 | } 35 | ``` 36 | 37 | 환경 구성 검토: 38 | 39 | ``` 40 | terraform plan 41 | ``` 42 | 43 | 환경 구성(코드 배포): 44 | 45 | ``` 46 | terraform apply 47 | ``` 48 | 49 | 환경 정리: 50 | 51 | ``` 52 | terraform destroy 53 | ``` 54 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/stage/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | module "webserver_cluster" { 6 | source = "../../../../modules/services/webserver-cluster" 7 | 8 | cluster_name = "webservers-stage" 9 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 10 | db_remote_state_key = "${var.db_remote_state_key}" 11 | 12 | instance_type = "t2.micro" 13 | min_size = 2 14 | max_size = 2 15 | enable_autoscaling = false 16 | enable_new_user_data = true 17 | } 18 | 19 | resource "aws_security_group_rule" "allow_testing_inbound" { 20 | type = "ingress" 21 | security_group_id = "${module.webserver_cluster.elb_security_group_id}" 22 | 23 | from_port = 12345 24 | to_port = 12345 25 | protocol = "tcp" 26 | cidr_blocks = ["0.0.0.0/0"] 27 | } 28 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/stage/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${module.webserver_cluster.elb_dns_name}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/live/stage/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_remote_state_bucket" { 2 | description = "The name of the S3 bucket used for the database's remote state storage" 3 | } 4 | 5 | variable "db_remote_state_key" { 6 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/modules/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 모듈 예제 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 자동 스케일링 그룹 설정을 통해서 무중단 배포가 가능 합니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"를 참고 하십시오. 6 | 7 | ## 시작 하기 8 | 9 | 모듈은 테라폼 구성 파일의 묶음이며 코드 전체의 여러 곳에서 재사용 가능하며 10 | [live/stage/services/webserver-cluster](../../../live/stage/services-webserver-cluster)와 11 | [live/prod/services/webserver-cluster](../../../live/prod/services-webserver-cluster)에서 이 공통된 모듈을 사용하는 예를 확인 할 수 있습니다. 12 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/modules/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_launch_configuration" "example" { 2 | image_id = "ami-40d28157" 3 | instance_type = "${var.instance_type}" 4 | security_groups = ["${aws_security_group.instance.id}"] 5 | 6 | user_data = "${element( 7 | concat(data.template_file.user_data.*.rendered, 8 | data.template_file.user_data_new.*.rendered), 9 | 0)}" 10 | 11 | lifecycle { 12 | create_before_destroy = true 13 | } 14 | } 15 | 16 | data "template_file" "user_data" { 17 | count = "${1 - var.enable_new_user_data}" 18 | 19 | template = "${file("${path.module}/user-data.sh")}" 20 | 21 | vars { 22 | server_port = "${var.server_port}" 23 | db_address = "${data.terraform_remote_state.db.address}" 24 | db_port = "${data.terraform_remote_state.db.port}" 25 | } 26 | } 27 | 28 | data "template_file" "user_data_new" { 29 | count = "${var.enable_new_user_data}" 30 | 31 | template = "${file("${path.module}/user-data-new.sh")}" 32 | 33 | vars { 34 | server_port = "${var.server_port}" 35 | } 36 | } 37 | 38 | resource "aws_autoscaling_group" "example" { 39 | launch_configuration = "${aws_launch_configuration.example.id}" 40 | availability_zones = ["${data.aws_availability_zones.all.names}"] 41 | load_balancers = ["${aws_elb.example.name}"] 42 | health_check_type = "ELB" 43 | 44 | min_size = "${var.min_size}" 45 | max_size = "${var.max_size}" 46 | 47 | tag { 48 | key = "Name" 49 | value = "${var.cluster_name}" 50 | propagate_at_launch = true 51 | } 52 | } 53 | 54 | resource "aws_autoscaling_schedule" "scale_out_during_business_hours" { 55 | count = "${var.enable_autoscaling}" 56 | 57 | scheduled_action_name = "scale-out-during-business-hours" 58 | min_size = 2 59 | max_size = 10 60 | desired_capacity = 10 61 | recurrence = "0 9 * * *" 62 | autoscaling_group_name = "${aws_autoscaling_group.example.name}" 63 | } 64 | 65 | resource "aws_autoscaling_schedule" "scale_in_at_night" { 66 | count = "${var.enable_autoscaling}" 67 | 68 | scheduled_action_name = "scale-in-at-night" 69 | min_size = 2 70 | max_size = 10 71 | desired_capacity = 2 72 | recurrence = "0 17 * * *" 73 | autoscaling_group_name = "${aws_autoscaling_group.example.name}" 74 | } 75 | 76 | resource "aws_security_group" "instance" { 77 | name = "${var.cluster_name}-instance" 78 | 79 | lifecycle { 80 | create_before_destroy = true 81 | } 82 | } 83 | 84 | resource "aws_security_group_rule" "allow_server_http_inbound" { 85 | type = "ingress" 86 | security_group_id = "${aws_security_group.instance.id}" 87 | 88 | from_port = "${var.server_port}" 89 | to_port = "${var.server_port}" 90 | protocol = "tcp" 91 | cidr_blocks = ["0.0.0.0/0"] 92 | } 93 | 94 | data "aws_availability_zones" "all" {} 95 | 96 | resource "aws_elb" "example" { 97 | name = "${var.cluster_name}" 98 | availability_zones = ["${data.aws_availability_zones.all.names}"] 99 | security_groups = ["${aws_security_group.elb.id}"] 100 | 101 | listener { 102 | lb_port = 80 103 | lb_protocol = "http" 104 | instance_port = "${var.server_port}" 105 | instance_protocol = "http" 106 | } 107 | 108 | health_check { 109 | healthy_threshold = 2 110 | unhealthy_threshold = 2 111 | timeout = 3 112 | interval = 30 113 | target = "HTTP:${var.server_port}/" 114 | } 115 | } 116 | 117 | resource "aws_security_group" "elb" { 118 | name = "${var.cluster_name}-elb" 119 | } 120 | 121 | resource "aws_security_group_rule" "allow_http_inbound" { 122 | type = "ingress" 123 | security_group_id = "${aws_security_group.elb.id}" 124 | 125 | from_port = 80 126 | to_port = 80 127 | protocol = "tcp" 128 | cidr_blocks = ["0.0.0.0/0"] 129 | } 130 | 131 | resource "aws_security_group_rule" "allow_all_outbound" { 132 | type = "egress" 133 | security_group_id = "${aws_security_group.elb.id}" 134 | 135 | from_port = 0 136 | to_port = 0 137 | protocol = "-1" 138 | cidr_blocks = ["0.0.0.0/0"] 139 | } 140 | 141 | data "terraform_remote_state" "db" { 142 | backend = "s3" 143 | 144 | config { 145 | bucket = "${var.db_remote_state_bucket}" 146 | key = "${var.db_remote_state_key}" 147 | region = "us-east-1" 148 | } 149 | } 150 | 151 | resource "aws_cloudwatch_metric_alarm" "high_cpu_utilization" { 152 | alarm_name = "${var.cluster_name}-high-cpu-utilization" 153 | namespace = "AWS/EC2" 154 | metric_name = "CPUUtilization" 155 | 156 | dimensions = { 157 | AutoScalingGroupName = "${aws_autoscaling_group.example.name}" 158 | } 159 | 160 | comparison_operator = "GreaterThanThreshold" 161 | evaluation_periods = 1 162 | period = 300 163 | statistic = "Average" 164 | threshold = 90 165 | unit = "Percent" 166 | } 167 | 168 | resource "aws_cloudwatch_metric_alarm" "low_cpu_credit_balance" { 169 | count = "${format("%.1s", var.instance_type) == "t" ? 1 : 0}" 170 | 171 | alarm_name = "${var.cluster_name}-low-cpu-credit-balance" 172 | namespace = "AWS/EC2" 173 | metric_name = "CPUCreditBalance" 174 | 175 | dimensions = { 176 | AutoScalingGroupName = "${aws_autoscaling_group.example.name}" 177 | } 178 | 179 | comparison_operator = "LessThanThreshold" 180 | evaluation_periods = 1 181 | period = 300 182 | statistic = "Minimum" 183 | threshold = 10 184 | unit = "Count" 185 | } 186 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/modules/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${aws_elb.example.dns_name}" 3 | } 4 | 5 | output "asg_name" { 6 | value = "${aws_autoscaling_group.example.name}" 7 | } 8 | 9 | output "elb_security_group_id" { 10 | value = "${aws_security_group.elb.id}" 11 | } 12 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/modules/services/webserver-cluster/user-data-new.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Hello, World, v2" > index.html 4 | nohup busybox httpd -f -p "${server_port}" & 5 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/modules/services/webserver-cluster/user-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat > index.html <Hello, World 5 |

DB address: ${db_address}

6 |

DB port: ${db_port}

7 | EOF 8 | 9 | nohup busybox httpd -f -p "${server_port}" & 10 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/loops-and-if-statements/modules/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "server_port" { 2 | description = "The port the server will use for HTTP requests" 3 | default = 8080 4 | } 5 | 6 | variable "cluster_name" { 7 | description = "The name to use for all the cluster resources" 8 | } 9 | 10 | variable "db_remote_state_bucket" { 11 | description = "The name of the S3 bucket for the database's remote state" 12 | } 13 | 14 | variable "db_remote_state_key" { 15 | description = "The path for the database's remote state in S3" 16 | } 17 | 18 | variable "instance_type" { 19 | description = "The type of EC2 Instances to run (e.g. t2.micro)" 20 | } 21 | 22 | variable "min_size" { 23 | description = "The minimum number of EC2 Instances in the ASG" 24 | } 25 | 26 | variable "max_size" { 27 | description = "The maximum number of EC2 Instances in the ASG" 28 | } 29 | 30 | variable "enable_autoscaling" { 31 | description = "If set to true, enable auto scaling" 32 | } 33 | 34 | variable "enable_new_user_data" { 35 | description = "If set to true, use the new User Data script" 36 | } 37 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/prod/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # RDS를 통한 MySQL 구성 예제 (상용 환경) 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)모듈을 통해 [RDS](https://aws.amazon.com/rds/)의 MySQL 데이터베이스 엔진을 4 | 구성 하는 실습 입니다. 5 | 6 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"를 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | [S3](https://aws.amazon.com/s3/)에 [원격 상태](https://www.terraform.io/docs/state/remote.html)를 저장하기 때문에 26 | main.tf 파일에 [기존에 생성한 버킷](https://github.com/stitchlabio/terraform-up-and-running-code/tree/master/code/terraform/03-terraform-state/file-layout-example/global/s3)으로 변경이 필요하며 상태 파일 잠금까지 함께 실습하고자 할 경우 dynamodb_table도 함께 변경: 27 | 28 | ``` 29 | terraform { 30 | backend "s3" { 31 | bucket = "(생성한 버킷 이름)" 32 | key = "live/prod/data-stores/mysql/terraform.tfstate" 33 | region = "us-east-1" 34 | encrypt = true 35 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 36 | } 37 | } 38 | ``` 39 | 40 | 환경 갱신(백엔드 구성을 위함): 41 | 42 | ``` 43 | terraform init 44 | ``` 45 | 46 | 환경 구성 검토: 47 | 48 | ``` 49 | terraform plan 50 | ``` 51 | 52 | 환경 구성(코드 배포): 53 | 54 | ``` 55 | terraform apply 56 | ``` 57 | 58 | 환경 정리: 59 | 60 | ``` 61 | terraform destroy 62 | ``` 63 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/prod/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_db_instance" "example" { 6 | engine = "mysql" 7 | allocated_storage = 10 8 | instance_class = "db.t2.micro" 9 | name = "example_database_prod" 10 | username = "admin" 11 | password = "${var.db_password}" 12 | skip_final_snapshot = true 13 | } 14 | 15 | terraform { 16 | backend "s3" { 17 | bucket = "(생성한 버킷 이름)" 18 | key = "live/prod/data-stores/mysql/terraform.tfstate" 19 | region = "us-east-1" 20 | encrypt = true 21 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 22 | } 23 | } -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/prod/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | output "address" { 2 | value = "${aws_db_instance.example.address}" 3 | } 4 | 5 | output "port" { 6 | value = "${aws_db_instance.example.port}" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/prod/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_password" { 2 | description = "The password for the database" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/prod/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 구성 예제 (상용 환경) 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 자동 스케일링 그룹 설정을 통해서 무중단 배포가 가능 합니다. 이 코드는 테라폼 모듈로 정의된 클러스터와 로드밸런서 [modules/services/webserver-cluster](../../../../modules/services/webserver-cluster)를 포함 합니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"를 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | * [data-stores/mysql](../../data-stores/mysql) 리소스가 구성 되어 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | `vars.tf` 파일 안에, [앞에서 구성한](../../data-stores/mysql) S3 버킷 이름과 원격에 저장된 MySQL 데이터베이스 상태 파일 이름을 입력: 26 | 27 | ```hcl 28 | variable "db_remote_state_bucket" { 29 | description = "The name of the S3 bucket used for the database's remote state storage" 30 | } 31 | 32 | variable "db_remote_state_key" { 33 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 34 | } 35 | ``` 36 | 37 | 환경 구성 검토: 38 | 39 | ``` 40 | terraform plan 41 | ``` 42 | 43 | 환경 구성(코드 배포): 44 | 45 | ``` 46 | terraform apply 47 | ``` 48 | 49 | 환경 정리: 50 | 51 | ``` 52 | terraform destroy 53 | ``` 54 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/prod/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | module "webserver_cluster" { 6 | source = "../../../../modules/services/webserver-cluster" 7 | 8 | ami = "ami-40d28157" 9 | server_text = "Hello, World" 10 | 11 | cluster_name = "webservers-prod" 12 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 13 | db_remote_state_key = "${var.db_remote_state_key}" 14 | 15 | instance_type = "m4.large" 16 | min_size = 2 17 | max_size = 10 18 | enable_autoscaling = true 19 | } 20 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/prod/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${module.webserver_cluster.elb_dns_name}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/prod/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_remote_state_bucket" { 2 | description = "The name of the S3 bucket used for the database's remote state storage" 3 | } 4 | 5 | variable "db_remote_state_key" { 6 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/stage/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # RDS를 통한 MySQL 구성 예제 (스테이징 환경) 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)모듈을 통해 [RDS](https://aws.amazon.com/rds/)의 MySQL 데이터베이스 엔진을 4 | 구성 하는 실습 입니다. 5 | 6 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"를 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | [S3](https://aws.amazon.com/s3/)에 [원격 상태](https://www.terraform.io/docs/state/remote.html)를 저장하기 때문에 26 | main.tf 파일에 [기존에 생성한 버킷](https://github.com/stitchlabio/terraform-up-and-running-code/tree/master/code/terraform/03-terraform-state/file-layout-example/global/s3)으로 변경이 필요하며 상태 파일 잠금까지 함께 실습하고자 할 경우 dynamodb_table도 함께 변경: 27 | 28 | ``` 29 | terraform { 30 | backend "s3" { 31 | bucket = "(생성한 버킷 이름)" 32 | key = "live/stage/data-stores/mysql/terraform.tfstate" 33 | region = "us-east-1" 34 | encrypt = true 35 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 36 | } 37 | } 38 | ``` 39 | 40 | 환경 갱신(백엔드 구성을 위함): 41 | 42 | ``` 43 | terraform init 44 | ``` 45 | 46 | 환경 구성 검토: 47 | 48 | ``` 49 | terraform plan 50 | ``` 51 | 52 | 환경 구성(코드 배포): 53 | 54 | ``` 55 | terraform apply 56 | ``` 57 | 58 | 환경 정리: 59 | 60 | ``` 61 | terraform destroy 62 | ``` 63 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/stage/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_db_instance" "example" { 6 | engine = "mysql" 7 | allocated_storage = 10 8 | instance_class = "db.t2.micro" 9 | name = "example_database_stage" 10 | username = "admin" 11 | password = "${var.db_password}" 12 | skip_final_snapshot = true 13 | } 14 | 15 | terraform { 16 | backend "s3" { 17 | bucket = "(생성한 버킷 이름)" 18 | key = "live/stage/data-stores/mysql/terraform.tfstate" 19 | region = "us-east-1" 20 | encrypt = true 21 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 22 | } 23 | } -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/stage/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | output "address" { 2 | value = "${aws_db_instance.example.address}" 3 | } 4 | 5 | output "port" { 6 | value = "${aws_db_instance.example.port}" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/stage/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_password" { 2 | description = "The password for the database" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/stage/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 구성 예제 (스테이징 환경) 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 자동 스케일링 그룹 설정을 통해서 무중단 배포가 가능 합니다. 클러스터와 로드밸런서 구성을 위해 [modules/services/webserver-cluster](../../../../modules/services/webserver-cluster) 모듈을 포함 하고 있습니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"을 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | * [data-stores/mysql](../../data-stores/mysql) 리소스가 구성 되어 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | `vars.tf` 파일 안에, [앞에서 구성한](../../data-stores/mysql) S3 버킷 이름과 원격에 저장된 MySQL 데이터베이스 상태 파일 이름을 입력: 26 | 27 | ```hcl 28 | variable "db_remote_state_bucket" { 29 | description = "The name of the S3 bucket used for the database's remote state storage" 30 | } 31 | 32 | variable "db_remote_state_key" { 33 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 34 | } 35 | ``` 36 | 37 | 환경 구성 검토: 38 | 39 | ``` 40 | terraform plan 41 | ``` 42 | 43 | 환경 구성(코드 배포): 44 | 45 | ``` 46 | terraform apply 47 | ``` 48 | 49 | 환경 정리: 50 | 51 | ``` 52 | terraform destroy 53 | ``` 54 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/stage/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | module "webserver_cluster" { 6 | source = "../../../../modules/services/webserver-cluster" 7 | 8 | ami = "ami-40d28157" 9 | server_text = "New server text" 10 | 11 | cluster_name = "webservers-stage" 12 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 13 | db_remote_state_key = "${var.db_remote_state_key}" 14 | 15 | instance_type = "t2.micro" 16 | min_size = 2 17 | max_size = 2 18 | enable_autoscaling = false 19 | } 20 | 21 | resource "aws_security_group_rule" "allow_testing_inbound" { 22 | type = "ingress" 23 | security_group_id = "${module.webserver_cluster.elb_security_group_id}" 24 | 25 | from_port = 12345 26 | to_port = 12345 27 | protocol = "tcp" 28 | cidr_blocks = ["0.0.0.0/0"] 29 | } 30 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/stage/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${module.webserver_cluster.elb_dns_name}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/live/stage/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_remote_state_bucket" { 2 | description = "The name of the S3 bucket used for the database's remote state storage" 3 | } 4 | 5 | variable "db_remote_state_key" { 6 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/modules/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 모듈 예제 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 자동 스케일링 그룹 설정을 통해서 무중단 배포가 가능 합니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제5장, 테라폼 팁과 요령: 반복문, 조건문, 배포 및 주의사항"를 참고 하십시오. 6 | 7 | ## 시작 하기 8 | 9 | 모듈은 테라폼 구성 파일의 묶음이며 코드 전체의 여러 곳에서 재사용 가능하다. 10 | [live/stage/services/webserver-cluster](../../../live/stage/services-webserver-cluster)와 11 | [live/prod/services/webserver-cluster](../../../live/prod/services-webserver-cluster)에서 이 공통된 모듈을 사용하는 예를 확인 할 수 있습니다. 12 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/modules/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_launch_configuration" "example" { 2 | image_id = "${var.ami}" 3 | instance_type = "${var.instance_type}" 4 | security_groups = ["${aws_security_group.instance.id}"] 5 | 6 | user_data = "${data.template_file.user_data.rendered}" 7 | 8 | lifecycle { 9 | create_before_destroy = true 10 | } 11 | } 12 | 13 | data "template_file" "user_data" { 14 | template = "${file("${path.module}/user-data.sh")}" 15 | 16 | vars { 17 | server_port = "${var.server_port}" 18 | db_address = "${data.terraform_remote_state.db.address}" 19 | db_port = "${data.terraform_remote_state.db.port}" 20 | server_text = "${var.server_text}" 21 | } 22 | } 23 | 24 | resource "aws_autoscaling_group" "example" { 25 | name = "${var.cluster_name}-${aws_launch_configuration.example.name}" 26 | 27 | launch_configuration = "${aws_launch_configuration.example.id}" 28 | availability_zones = ["${data.aws_availability_zones.all.names}"] 29 | load_balancers = ["${aws_elb.example.name}"] 30 | health_check_type = "ELB" 31 | 32 | min_size = "${var.min_size}" 33 | max_size = "${var.max_size}" 34 | min_elb_capacity = "${var.min_size}" 35 | 36 | lifecycle { 37 | create_before_destroy = true 38 | } 39 | 40 | tag { 41 | key = "Name" 42 | value = "${var.cluster_name}" 43 | propagate_at_launch = true 44 | } 45 | } 46 | 47 | resource "aws_autoscaling_schedule" "scale_out_during_business_hours" { 48 | count = "${var.enable_autoscaling}" 49 | 50 | scheduled_action_name = "scale-out-during-business-hours" 51 | min_size = 2 52 | max_size = 10 53 | desired_capacity = 10 54 | recurrence = "0 9 * * *" 55 | autoscaling_group_name = "${aws_autoscaling_group.example.name}" 56 | } 57 | 58 | resource "aws_autoscaling_schedule" "scale_in_at_night" { 59 | count = "${var.enable_autoscaling}" 60 | 61 | scheduled_action_name = "scale-in-at-night" 62 | min_size = 2 63 | max_size = 10 64 | desired_capacity = 2 65 | recurrence = "0 17 * * *" 66 | autoscaling_group_name = "${aws_autoscaling_group.example.name}" 67 | } 68 | 69 | resource "aws_security_group" "instance" { 70 | name = "${var.cluster_name}-instance" 71 | 72 | lifecycle { 73 | create_before_destroy = true 74 | } 75 | } 76 | 77 | resource "aws_security_group_rule" "allow_server_http_inbound" { 78 | type = "ingress" 79 | security_group_id = "${aws_security_group.instance.id}" 80 | 81 | from_port = "${var.server_port}" 82 | to_port = "${var.server_port}" 83 | protocol = "tcp" 84 | cidr_blocks = ["0.0.0.0/0"] 85 | } 86 | 87 | data "aws_availability_zones" "all" {} 88 | 89 | resource "aws_elb" "example" { 90 | name = "${var.cluster_name}" 91 | availability_zones = ["${data.aws_availability_zones.all.names}"] 92 | security_groups = ["${aws_security_group.elb.id}"] 93 | 94 | listener { 95 | lb_port = 80 96 | lb_protocol = "http" 97 | instance_port = "${var.server_port}" 98 | instance_protocol = "http" 99 | } 100 | 101 | health_check { 102 | healthy_threshold = 2 103 | unhealthy_threshold = 2 104 | timeout = 3 105 | interval = 30 106 | target = "HTTP:${var.server_port}/" 107 | } 108 | 109 | lifecycle { 110 | create_before_destroy = true 111 | } 112 | } 113 | 114 | resource "aws_security_group" "elb" { 115 | name = "${var.cluster_name}-elb" 116 | 117 | lifecycle { 118 | create_before_destroy = true 119 | } 120 | } 121 | 122 | resource "aws_security_group_rule" "allow_http_inbound" { 123 | type = "ingress" 124 | security_group_id = "${aws_security_group.elb.id}" 125 | 126 | from_port = 80 127 | to_port = 80 128 | protocol = "tcp" 129 | cidr_blocks = ["0.0.0.0/0"] 130 | } 131 | 132 | resource "aws_security_group_rule" "allow_all_outbound" { 133 | type = "egress" 134 | security_group_id = "${aws_security_group.elb.id}" 135 | 136 | from_port = 0 137 | to_port = 0 138 | protocol = "-1" 139 | cidr_blocks = ["0.0.0.0/0"] 140 | } 141 | 142 | data "terraform_remote_state" "db" { 143 | backend = "s3" 144 | 145 | config { 146 | bucket = "${var.db_remote_state_bucket}" 147 | key = "${var.db_remote_state_key}" 148 | region = "us-east-1" 149 | } 150 | } 151 | 152 | resource "aws_cloudwatch_metric_alarm" "high_cpu_utilization" { 153 | alarm_name = "${var.cluster_name}-high-cpu-utilization" 154 | namespace = "AWS/EC2" 155 | metric_name = "CPUUtilization" 156 | 157 | dimensions = { 158 | AutoScalingGroupName = "${aws_autoscaling_group.example.name}" 159 | } 160 | 161 | comparison_operator = "GreaterThanThreshold" 162 | evaluation_periods = 1 163 | period = 300 164 | statistic = "Average" 165 | threshold = 90 166 | unit = "Percent" 167 | } 168 | 169 | resource "aws_cloudwatch_metric_alarm" "low_cpu_credit_balance" { 170 | count = "${format("%.1s", var.instance_type) == "t" ? 1 : 0}" 171 | 172 | alarm_name = "${var.cluster_name}-low-cpu-credit-balance" 173 | namespace = "AWS/EC2" 174 | metric_name = "CPUCreditBalance" 175 | 176 | dimensions = { 177 | AutoScalingGroupName = "${aws_autoscaling_group.example.name}" 178 | } 179 | 180 | comparison_operator = "LessThanThreshold" 181 | evaluation_periods = 1 182 | period = 300 183 | statistic = "Minimum" 184 | threshold = 10 185 | unit = "Count" 186 | } 187 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/modules/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${aws_elb.example.dns_name}" 3 | } 4 | 5 | output "asg_name" { 6 | value = "${aws_autoscaling_group.example.name}" 7 | } 8 | 9 | output "elb_security_group_id" { 10 | value = "${aws_security_group.elb.id}" 11 | } 12 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/modules/services/webserver-cluster/user-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat > index.html <${server_text} 5 |

DB address: ${db_address}

6 |

DB port: ${db_port}

7 | EOF 8 | 9 | nohup busybox httpd -f -p "${server_port}" & 10 | -------------------------------------------------------------------------------- /code/terraform/05-tips-and-tricks/zero-downtime-deployment/modules/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "server_port" { 2 | description = "The port the server will use for HTTP requests" 3 | default = 8080 4 | } 5 | 6 | variable "cluster_name" { 7 | description = "The name to use for all the cluster resources" 8 | } 9 | 10 | variable "db_remote_state_bucket" { 11 | description = "The name of the S3 bucket for the database's remote state" 12 | } 13 | 14 | variable "db_remote_state_key" { 15 | description = "The path for the database's remote state in S3" 16 | } 17 | 18 | variable "instance_type" { 19 | description = "The type of EC2 Instances to run (e.g. t2.micro)" 20 | } 21 | 22 | variable "min_size" { 23 | description = "The minimum number of EC2 Instances in the ASG" 24 | } 25 | 26 | variable "max_size" { 27 | description = "The maximum number of EC2 Instances in the ASG" 28 | } 29 | 30 | variable "enable_autoscaling" { 31 | description = "If set to true, enable auto scaling" 32 | } 33 | 34 | variable "ami" { 35 | description = "The AMI to run in the cluster" 36 | default = "ami-40d28157" 37 | } 38 | 39 | variable "server_text" { 40 | description = "The text the web server should return" 41 | default = "Hello, World" 42 | } 43 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/prod/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # RDS를 통한 MySQL 구성 예제 (상용 환경) 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)모듈을 통해 [RDS](https://aws.amazon.com/rds/)의 MySQL 데이터베이스 엔진을 4 | 구성 하는 실습 입니다. 5 | 6 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제6장, 테라폼을 팀에서 사용하기"를 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | [S3](https://aws.amazon.com/s3/)에 [원격 상태](https://www.terraform.io/docs/state/remote.html)를 저장하기 때문에 26 | main.tf 파일에 [기존에 생성한 버킷](https://github.com/stitchlabio/terraform-up-and-running-code/tree/master/code/terraform/03-terraform-state/file-layout-example/global/s3)으로 변경이 필요하며 상태 파일 잠금까지 함께 실습하고자 할 경우 dynamodb_table도 함께 변경: 27 | 28 | ``` 29 | terraform { 30 | backend "s3" { 31 | bucket = "(생성한 버킷 이름)" 32 | key = "live/prod/data-stores/mysql/terraform.tfstate" 33 | region = "us-east-1" 34 | encrypt = true 35 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 36 | } 37 | } 38 | ``` 39 | 40 | 환경 갱신(백엔드 구성을 위함): 41 | 42 | ``` 43 | terraform init 44 | ``` 45 | 46 | 환경 구성 검토: 47 | 48 | ``` 49 | terraform plan 50 | ``` 51 | 52 | 환경 구성(코드 배포): 53 | 54 | ``` 55 | terraform apply 56 | ``` 57 | 58 | 환경 정리: 59 | 60 | ``` 61 | terraform destroy 62 | ``` 63 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/prod/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_db_instance" "example" { 6 | engine = "mysql" 7 | allocated_storage = 10 8 | instance_class = "db.t2.micro" 9 | name = "example_database_prod" 10 | username = "admin" 11 | password = "${var.db_password}" 12 | skip_final_snapshot = true 13 | } 14 | 15 | terraform { 16 | backend "s3" { 17 | bucket = "(생성한 버킷 이름)" 18 | key = "live/prod/data-stores/mysql/terraform.tfstate" 19 | region = "us-east-1" 20 | encrypt = true 21 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/prod/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | output "address" { 2 | value = "${aws_db_instance.example.address}" 3 | } 4 | 5 | output "port" { 6 | value = "${aws_db_instance.example.port}" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/prod/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_password" { 2 | description = "The password for the database" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/prod/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 구성 예제 (상용 환경) 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 이 코드는 테라폼 모듈로 정의된 클러스터와 로드밸런서 [modules/services/webserver-cluster](../../../../../module-example/modules/services/webserver-cluster)를 포함 합니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제6장, 테라폼을 팀에서 사용하기"를 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | * [data-stores/mysql](../../data-stores/mysql) 리소스가 구성 되어 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | `vars.tf` 파일 안에, [앞에서 구성한](../../data-stores/mysql) S3 버킷 이름과 원격에 저장된 MySQL 데이터베이스 상태 파일 이름을 입력: 26 | 27 | ```hcl 28 | variable "db_remote_state_bucket" { 29 | description = "The name of the S3 bucket used for the database's remote state storage" 30 | } 31 | 32 | variable "db_remote_state_key" { 33 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 34 | } 35 | ``` 36 | 37 | 환경 구성 검토: 38 | 39 | ``` 40 | terraform plan 41 | ``` 42 | 43 | 환경 구성(코드 배포): 44 | 45 | ``` 46 | terraform apply 47 | ``` 48 | 49 | 환경 정리: 50 | 51 | ``` 52 | terraform destroy 53 | ``` 54 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/prod/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "${var.aws_region}" 3 | } 4 | 5 | module "webserver_cluster" { 6 | source = "../../../../modules/services/webserver-cluster" 7 | 8 | ami = "${data.aws_ami.ubuntu.id}" 9 | server_text = "Hello, World" 10 | 11 | aws_region = "${var.aws_region}" 12 | cluster_name = "${var.cluster_name}" 13 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 14 | db_remote_state_key = "${var.db_remote_state_key}" 15 | 16 | instance_type = "m4.large" 17 | min_size = 2 18 | max_size = 10 19 | enable_autoscaling = true 20 | } 21 | 22 | data "aws_ami" "ubuntu" { 23 | most_recent = true 24 | owners = ["099720109477"] # Canonical 25 | 26 | filter { 27 | name = "virtualization-type" 28 | values = ["hvm"] 29 | } 30 | 31 | filter { 32 | name = "architecture" 33 | values = ["x86_64"] 34 | } 35 | 36 | filter { 37 | name = "image-type" 38 | values = ["machine"] 39 | } 40 | 41 | filter { 42 | name = "name" 43 | values = ["ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*"] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/prod/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${module.webserver_cluster.elb_dns_name}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/prod/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | description = "The AWS region to use" 3 | default = "us-east-1" 4 | } 5 | 6 | variable "cluster_name" { 7 | description = "The name to use for all the cluster resources" 8 | default = "webservers-prod" 9 | } 10 | 11 | variable "db_remote_state_bucket" { 12 | description = "The S3 bucket used for the database's remote state" 13 | } 14 | 15 | variable "db_remote_state_key" { 16 | description = "The path for the database's remote state in S3" 17 | default = "prod/data-stores/mysql/terraform.tfstate" 18 | } 19 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/stage/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # RDS를 통한 MySQL 구성 예제 (스테이징 환경) 2 | 3 | 이번 실습은 [Terraform](https://www.terraform.io/)모듈을 통해 [RDS](https://aws.amazon.com/rds/)의 MySQL 데이터베이스 엔진을 4 | 구성 하는 실습 입니다. 5 | 6 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제6장, 테라폼을 팀에서 사용하기"를 참고 하십시오. 7 | 8 | ## 사전 준비 사항 9 | 10 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 11 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | [S3](https://aws.amazon.com/s3/)에 [원격 상태](https://www.terraform.io/docs/state/remote.html)를 저장하기 때문에 26 | main.tf 파일에 [기존에 생성한 버킷](https://github.com/stitchlabio/terraform-up-and-running-code/tree/master/code/terraform/03-terraform-state/file-layout-example/global/s3)으로 변경이 필요하며 상태 파일 잠금까지 함께 실습하고자 할 경우 dynamodb_table도 함께 변경: 27 | 28 | ``` 29 | terraform { 30 | backend "s3" { 31 | bucket = "(생성한 버킷 이름)" 32 | key = "live/stage/data-stores/mysql/terraform.tfstate" 33 | region = "us-east-1" 34 | encrypt = true 35 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 36 | } 37 | } 38 | ``` 39 | 40 | 환경 갱신(백엔드 구성을 위함): 41 | 42 | ``` 43 | terraform init 44 | ``` 45 | 46 | 환경 구성 검토: 47 | 48 | ``` 49 | terraform plan 50 | ``` 51 | 52 | 환경 구성(코드 배포): 53 | 54 | ``` 55 | terraform apply 56 | ``` 57 | 58 | 환경 정리: 59 | 60 | ``` 61 | terraform destroy 62 | ``` 63 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/stage/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-east-1" 3 | } 4 | 5 | resource "aws_db_instance" "example" { 6 | engine = "mysql" 7 | allocated_storage = 10 8 | instance_class = "db.t2.micro" 9 | name = "example_database_stage" 10 | username = "admin" 11 | password = "${var.db_password}" 12 | skip_final_snapshot = true 13 | } 14 | 15 | terraform { 16 | backend "s3" { 17 | bucket = "(생성한 버킷 이름)" 18 | key = "live/stage/data-stores/mysql/terraform.tfstate" 19 | region = "us-east-1" 20 | encrypt = true 21 | # dynamodb_table = "(생성한 DynamoDB 테이블 이름)" 22 | } 23 | } -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/stage/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | output "address" { 2 | value = "${aws_db_instance.example.address}" 3 | } 4 | 5 | output "port" { 6 | value = "${aws_db_instance.example.port}" 7 | } 8 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/stage/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | variable "db_password" { 2 | description = "The password for the database" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/stage/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 구성 예제 (스테이징 환경) 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 자동 스케일링 그룹 설정을 통해서 무중단 배포가 가능 합니다. 클러스터와 로드밸런서 구성을 위해 [modules/services/webserver-cluster](../../../../modules/services/webserver-cluster) 모듈을 포함 하고 있습니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제6장, 테라폼을 팀에서 사용하기"을 참고 하십시오. 6 | 7 | ## 사전 준비 사항 8 | 9 | * [Terraform](https://www.terraform.io/)이 설치 되어 있어야 합니다. 10 | * [Amazon Web Services (AWS) account](http://aws.amazon.com/) 계정을 보유 하고 있어야 합니다. 11 | * [data-stores/mysql](../../data-stores/mysql) 리소스가 구성 되어 있어야 합니다. 12 | 13 | ## 시작 하기 14 | 15 | **이 실습은 실제 AWS 리소스를 생성합니다. 대부분 [AWS Free Tier](https://aws.amazon.com/free/)로 지원되는 범위안에서 자원을 생성하고 활용하나 사용자의 조건에 따라서 비용이 일부 발생 할 수도 있습니다. 비용 발생에 대한 부분에 대해서는 실습 제공자가 책임지지 않으며 비용에 주의하여 실습을 진행하십시오. [비용 알람](http://bit.ly/2Nryf1C)을 설정해놓는 것을 권장합니다.** 16 | 17 | [AWS 엑세스 키](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) 18 | 를 환경 변수로 설정: 19 | 20 | ``` 21 | export AWS_ACCESS_KEY_ID=(your access key id) 22 | export AWS_SECRET_ACCESS_KEY=(your secret access key) 23 | ``` 24 | 25 | `vars.tf` 파일 안에, [앞에서 구성한](../../data-stores/mysql) S3 버킷 이름과 원격에 저장된 MySQL 데이터베이스 상태 파일 이름을 입력: 26 | 27 | ```hcl 28 | variable "db_remote_state_bucket" { 29 | description = "The name of the S3 bucket used for the database's remote state storage" 30 | } 31 | 32 | variable "db_remote_state_key" { 33 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 34 | } 35 | ``` 36 | 37 | 환경 구성 검토: 38 | 39 | ``` 40 | terraform plan 41 | ``` 42 | 43 | 환경 구성(코드 배포): 44 | 45 | ``` 46 | terraform apply 47 | ``` 48 | 49 | 환경 정리: 50 | 51 | ``` 52 | terraform destroy 53 | ``` 54 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/stage/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "${var.aws_region}" 3 | } 4 | 5 | module "webserver_cluster" { 6 | source = "../../../../modules/services/webserver-cluster" 7 | 8 | ami = "${data.aws_ami.ubuntu.id}" 9 | server_text = "New server text" 10 | 11 | aws_region = "${var.aws_region}" 12 | cluster_name = "${var.cluster_name}" 13 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 14 | db_remote_state_key = "${var.db_remote_state_key}" 15 | 16 | instance_type = "t2.micro" 17 | min_size = 2 18 | max_size = 2 19 | enable_autoscaling = false 20 | } 21 | 22 | resource "aws_security_group_rule" "allow_testing_inbound" { 23 | type = "ingress" 24 | security_group_id = "${module.webserver_cluster.elb_security_group_id}" 25 | 26 | from_port = 12345 27 | to_port = 12345 28 | protocol = "tcp" 29 | cidr_blocks = ["0.0.0.0/0"] 30 | } 31 | 32 | data "aws_ami" "ubuntu" { 33 | most_recent = true 34 | owners = ["099720109477"] # Canonical 35 | 36 | filter { 37 | name = "virtualization-type" 38 | values = ["hvm"] 39 | } 40 | 41 | filter { 42 | name = "architecture" 43 | values = ["x86_64"] 44 | } 45 | 46 | filter { 47 | name = "image-type" 48 | values = ["machine"] 49 | } 50 | 51 | filter { 52 | name = "name" 53 | values = ["ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*"] 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/stage/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${module.webserver_cluster.elb_dns_name}" 3 | } 4 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/live/stage/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | description = "The AWS region to use" 3 | default = "us-east-1" 4 | } 5 | 6 | variable "cluster_name" { 7 | description = "The name to use for all the cluster resources" 8 | default = "webservers-stage" 9 | } 10 | 11 | variable "db_remote_state_bucket" { 12 | description = "The S3 bucket used for the database's remote state" 13 | } 14 | 15 | variable "db_remote_state_key" { 16 | description = "The path for the database's remote state in S3" 17 | default = "stage/data-stores/mysql/terraform.tfstate" 18 | } 19 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/modules/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # 웹서버 클러스터 모듈 예제 2 | 3 | 이 폴더는 [Terraform](https://www.terraform.io/)의 [EC2](https://aws.amazon.com/ec2/), 자동 스케일링 그룹([Auto Scaling](https://aws.amazon.com/autoscaling/))과 로드밸런서([ELB](https://aws.amazon.com/elasticloadbalancing/))를 통해 웹서버 클러스터를 생성하는 실습 예제를 포함하고 있으며 로드밸런서를 통해 80포트로 오는 `/` URL 요청에 대해 "Hello, World"에 대한 응답을 수행 합니다. 자동 스케일링 그룹 설정을 통해서 무중단 배포가 가능 합니다. 4 | 5 | 자세한 내용은 *[테라폼 설치에서 운영까지](http://www.terraformupandrunning.com)* 서적의 "제6장, 테라폼을 팀에서 사용하기"를 참고 하십시오. 6 | 7 | ## 시작 하기 8 | 9 | 모듈은 테라폼 구성 파일의 묶음이며 코드 전체의 여러 곳에서 재사용 가능하다. 10 | [live/stage/services/webserver-cluster](../../../live/stage/services-webserver-cluster)와 11 | [live/prod/services/webserver-cluster](../../../live/prod/services-webserver-cluster)에서 이 공통된 모듈을 사용하는 예를 확인 할 수 있습니다. 12 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/modules/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_launch_configuration" "example" { 2 | image_id = "${var.ami}" 3 | instance_type = "${var.instance_type}" 4 | security_groups = ["${aws_security_group.instance.id}"] 5 | 6 | user_data = "${data.template_file.user_data.rendered}" 7 | 8 | lifecycle { 9 | create_before_destroy = true 10 | } 11 | } 12 | 13 | data "template_file" "user_data" { 14 | template = "${file("${path.module}/user-data.sh")}" 15 | 16 | vars { 17 | server_port = "${var.server_port}" 18 | db_address = "${data.terraform_remote_state.db.address}" 19 | db_port = "${data.terraform_remote_state.db.port}" 20 | server_text = "${var.server_text}" 21 | } 22 | } 23 | 24 | resource "aws_autoscaling_group" "example" { 25 | name = "${var.cluster_name}-${aws_launch_configuration.example.name}" 26 | launch_configuration = "${aws_launch_configuration.example.id}" 27 | availability_zones = ["${data.aws_availability_zones.all.names}"] 28 | load_balancers = ["${aws_elb.example.name}"] 29 | health_check_type = "ELB" 30 | 31 | min_size = "${var.min_size}" 32 | max_size = "${var.max_size}" 33 | min_elb_capacity = "${var.min_size}" 34 | 35 | lifecycle { 36 | create_before_destroy = true 37 | } 38 | 39 | tag { 40 | key = "Name" 41 | value = "${var.cluster_name}" 42 | propagate_at_launch = true 43 | } 44 | } 45 | 46 | resource "aws_autoscaling_schedule" "scale_out_during_business_hours" { 47 | count = "${var.enable_autoscaling}" 48 | 49 | scheduled_action_name = "scale-out-during-business-hours" 50 | min_size = 2 51 | max_size = 10 52 | desired_capacity = 10 53 | recurrence = "0 9 * * *" 54 | autoscaling_group_name = "${aws_autoscaling_group.example.name}" 55 | } 56 | 57 | resource "aws_autoscaling_schedule" "scale_in_at_night" { 58 | count = "${var.enable_autoscaling}" 59 | 60 | scheduled_action_name = "scale-in-at-night" 61 | min_size = 2 62 | max_size = 10 63 | desired_capacity = 2 64 | recurrence = "0 17 * * *" 65 | autoscaling_group_name = "${aws_autoscaling_group.example.name}" 66 | } 67 | 68 | resource "aws_security_group" "instance" { 69 | name = "${var.cluster_name}-instance" 70 | 71 | lifecycle { 72 | create_before_destroy = true 73 | } 74 | } 75 | 76 | resource "aws_security_group_rule" "allow_server_http_inbound" { 77 | type = "ingress" 78 | security_group_id = "${aws_security_group.instance.id}" 79 | 80 | from_port = "${var.server_port}" 81 | to_port = "${var.server_port}" 82 | protocol = "tcp" 83 | cidr_blocks = ["0.0.0.0/0"] 84 | } 85 | 86 | data "aws_availability_zones" "all" {} 87 | 88 | resource "aws_elb" "example" { 89 | name = "${var.cluster_name}" 90 | availability_zones = ["${data.aws_availability_zones.all.names}"] 91 | security_groups = ["${aws_security_group.elb.id}"] 92 | 93 | listener { 94 | lb_port = 80 95 | lb_protocol = "http" 96 | instance_port = "${var.server_port}" 97 | instance_protocol = "http" 98 | } 99 | 100 | health_check { 101 | healthy_threshold = 2 102 | unhealthy_threshold = 2 103 | timeout = 3 104 | interval = 30 105 | target = "HTTP:${var.server_port}/" 106 | } 107 | 108 | lifecycle { 109 | create_before_destroy = true 110 | } 111 | } 112 | 113 | resource "aws_security_group" "elb" { 114 | name = "${var.cluster_name}-elb" 115 | 116 | lifecycle { 117 | create_before_destroy = true 118 | } 119 | } 120 | 121 | resource "aws_security_group_rule" "allow_http_inbound" { 122 | type = "ingress" 123 | security_group_id = "${aws_security_group.elb.id}" 124 | 125 | from_port = 80 126 | to_port = 80 127 | protocol = "tcp" 128 | cidr_blocks = ["0.0.0.0/0"] 129 | } 130 | 131 | resource "aws_security_group_rule" "allow_all_outbound" { 132 | type = "egress" 133 | security_group_id = "${aws_security_group.elb.id}" 134 | 135 | from_port = 0 136 | to_port = 0 137 | protocol = "-1" 138 | cidr_blocks = ["0.0.0.0/0"] 139 | } 140 | 141 | data "terraform_remote_state" "db" { 142 | backend = "s3" 143 | 144 | config { 145 | bucket = "${var.db_remote_state_bucket}" 146 | key = "${var.db_remote_state_key}" 147 | region = "${var.aws_region}" 148 | } 149 | } 150 | 151 | resource "aws_cloudwatch_metric_alarm" "high_cpu_utilization" { 152 | alarm_name = "${var.cluster_name}-high-cpu-utilization" 153 | namespace = "AWS/EC2" 154 | metric_name = "CPUUtilization" 155 | 156 | dimensions = { 157 | AutoScalingGroupName = "${aws_autoscaling_group.example.name}" 158 | } 159 | 160 | comparison_operator = "GreaterThanThreshold" 161 | evaluation_periods = 1 162 | period = 300 163 | statistic = "Average" 164 | threshold = 90 165 | unit = "Percent" 166 | } 167 | 168 | resource "aws_cloudwatch_metric_alarm" "low_cpu_credit_balance" { 169 | count = "${format("%.1s", var.instance_type) == "t" ? 1 : 0}" 170 | 171 | alarm_name = "${var.cluster_name}-low-cpu-credit-balance" 172 | namespace = "AWS/EC2" 173 | metric_name = "CPUCreditBalance" 174 | 175 | dimensions = { 176 | AutoScalingGroupName = "${aws_autoscaling_group.example.name}" 177 | } 178 | 179 | comparison_operator = "LessThanThreshold" 180 | evaluation_periods = 1 181 | period = 300 182 | statistic = "Minimum" 183 | threshold = 10 184 | unit = "Count" 185 | } 186 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/modules/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | output "elb_dns_name" { 2 | value = "${aws_elb.example.dns_name}" 3 | } 4 | 5 | output "asg_name" { 6 | value = "${aws_autoscaling_group.example.name}" 7 | } 8 | 9 | output "elb_security_group_id" { 10 | value = "${aws_security_group.elb.id}" 11 | } 12 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/modules/services/webserver-cluster/user-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat > index.html <Hello, World 5 |

DB address: ${db_address}

6 |

DB port: ${db_port}

7 | EOF 8 | 9 | nohup busybox httpd -f -p "${server_port}" & 10 | -------------------------------------------------------------------------------- /code/terraform/06-terraform-team/modules/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | variable "server_port" { 2 | description = "The port the server will use for HTTP requests" 3 | default = 8080 4 | } 5 | 6 | variable "cluster_name" { 7 | description = "The name to use for all the cluster resources" 8 | } 9 | 10 | variable "db_remote_state_bucket" { 11 | description = "The name of the S3 bucket for the database's remote state" 12 | } 13 | 14 | variable "db_remote_state_key" { 15 | description = "The path for the database's remote state in S3" 16 | } 17 | 18 | variable "instance_type" { 19 | description = "The type of EC2 Instances to run (e.g. t2.micro)" 20 | } 21 | 22 | variable "min_size" { 23 | description = "The minimum number of EC2 Instances in the ASG" 24 | } 25 | 26 | variable "max_size" { 27 | description = "The maximum number of EC2 Instances in the ASG" 28 | } 29 | 30 | variable "enable_autoscaling" { 31 | description = "If set to true, enable auto scaling" 32 | } 33 | 34 | variable "ami" { 35 | description = "The AMI to run in the cluster" 36 | default = "ami-40d28157" 37 | } 38 | 39 | variable "server_text" { 40 | description = "The text the web server should return" 41 | default = "Hello, World" 42 | } 43 | 44 | variable "aws_region" { 45 | description = "The AWS region to use" 46 | } 47 | --------------------------------------------------------------------------------