diff --git a/README.ko.md b/README.ko.md new file mode 100644 index 0000000..4e6fa5d --- /dev/null +++ b/README.ko.md @@ -0,0 +1,65 @@ +[[English](README.md)] [[한국어](README.ko.md)] + +# 시스템 매니저(AWS Systems Manager) +[시스템 매니저(AWS Systems Manager)](https://aws.amazon.com/systems-manager/)는 여러 분의 AWS 인프라스트럭처에 대한 가시성과 제어권을 제공합니다. 시스템 매니저는 통합 환경을 제공하여, 다양한 AWS 서비스의 운영 관련 데이터를 모아 볼 수 있도록 해주고 AWS 자원에 대해 운영 작업을 자동화할 수 있도록 해줍니다. + +## 예제 +- [Amazon EC2 Blueprint](https://github.com/Young-ook/terraform-aws-ssm/tree/main/examples/blueprint) +- [AWS FIS Blueprint (Chaos Engineering)](https://github.com/Young-ook/terraform-aws-fis/blob/main/examples/blueprint) + +## 시작하기 +### AWS CLI (Command-Line Interface) +다음의 공식 안내 문서를 참고하여 AWS CLI 설치 및 설정을 할 수 있습니다. +- [AWS CLI Installation](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) +- [AWS CLI Configuration](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) + +설치를 완료했다면, 버전 확인을 통해 설지가 잘 되었는 지 판단할 수 있습니다: +``` +aws --version +aws-cli/2.5.8 Python/3.9.11 Darwin/21.4.0 exe/x86_64 prompt/off +``` + +### 테라폼(Terraform) +테라폼은 여러 분의 인프라스트럭처를 안전하게, 그리고 재현가능하게 생성하고 관리할 수 있도록 있도록 만들어주는 오픈소스 소프트웨어 도구 입니다. + +#### 설치 +공식 문서의 안내에 따라 테라폼 실행 바이너리 파일을 설치합니다. 자세한 안내사항은 [Install Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli) 문서를 참조하시길 바랍니다. + +또는, 직접 특정 버전의 테라폼을 선택해서 설치할 수 있습니다. [Downloads](https://www.terraform.io/downloads.html)페이지로 이동해서 여러 분의 시스템 환경에 맞는 패키지를 찾습니다. 그리고 압축 파일을 선택한 뒤 내려 받습니다. 압축을 풀면 생성되는 파일을 여러 분의 `PATH` 경로에 포함된 디렉토리로 옮겨서 설치를 완료합니다. + +또는, [tfenv](https://github.com/tfutils/tfenv)를 사용할 수 있습니다. 여러 버전의 테라폼 실행 파일을 설치하고 변경하는 일을 쉽게 만들어 주는 도구입니다. + +먼저, brew를 이용해서 tfenv를 설치합니다. +``` +brew install tfenv +``` +다음, tfenv를 이용해서 테라폼을 설치할 수 있습니다. +``` +tfenv install +tfenv use +``` +또한 이 도구는 테라폼 버전 v0.12로 업그레이드 하는 것에 유용합니다. 해당 버전은 테라폼의 언어 관련한 개선 사항이 포함된 중요한 배포판입니다. 그러나 0.11 버전과 0.12 버전은 매우 다릅니다. 그래서 만약 몇몇 코드가 이전 버전으로 되어 있고, 나머지는 0.12 버전일 수도 있습니다. 그런 경우 이 도구를 이용하여 테라폼 실행 버전을 간단한 명령 한 줄로 전환할 수 있습니다. +``` +tfenv list +tfenv install latest +tfenv use +``` + +### 생성 +``` +module "ec2" { + source = "Young-ook/ssm/aws" + name = "ssm" + tags = { env = "test" } +} +``` +테라폼 실행: +``` +terraform init +terraform apply +``` + +### 연결 +예제에서 사용한 EC2 인스턴스는 시스템 매니저를 사용해서 접속할 수 있습니다. AWS 관리 콘솔화면에서 EC2 서비스 페이지로 이동합니다. 인스턴스를 선택하고 '연결' 또는 'Connect' 단추를 누릅니다. 그러면, EC2를 접속할 수 있는 여러 방법이 표시되는데, 그 중 세션 매니저(Session Manager)를 선택합니다. 이 후 안내를 따라 인스턴스 내부에 접속합니다. + +![aws-fis-ec2-disk-stress](images/aws-fis-ec2-disk-stress.png) diff --git a/README.md b/README.md index 24a4644..d244432 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ +[[English](README.md)] [[한국어](README.ko.md)] + # AWS Systems Manager [AWS Systems Manager](https://aws.amazon.com/systems-manager/) gives you visibility and control of your infrastructure on AWS. Systems Manager provides a unified user interface so you can view operational data from multiple AWS services and allows you to automate operational tasks across your AWS resources. ## Examples - [Amazon EC2 Blueprint](https://github.com/Young-ook/terraform-aws-ssm/tree/main/examples/blueprint) -- [AWS Systems Manager](https://github.com/Young-ook/terraform-aws-ssm/tree/main/examples/ssm-document) -- [Chaos Engineering with AWS Fault Injection Simulator](https://github.com/Young-ook/terraform-aws-fis) +- [AWS FIS Blueprint (Chaos Engineering)](https://github.com/Young-ook/terraform-aws-fis/blob/main/examples/blueprint) ## Getting started ### AWS CLI diff --git a/examples/blueprint/apps/README.ko.md b/examples/blueprint/apps/README.ko.md index 2c5f7ee..f846a2c 100644 --- a/examples/blueprint/apps/README.ko.md +++ b/examples/blueprint/apps/README.ko.md @@ -45,6 +45,3 @@ Launching a new EC2 instance into warm pool: i-0180961b460339ed3 Duration: 215s ``` ![aws-asg-activity-history](../../../images/aws-asg-activity-history.png) - -### 연결 -예제에서 사용한 EC2 인스턴스는 시스템 매니저를 사용해서 접속할 수 있습니다. AWS 관리 콘솔화면에서 EC2 서비스 페이지로 이동합니다. 인스턴스를 선택하고 '연결' 또는 'Connect' 단추를 누릅니다. 그러면, EC2를 접속할 수 있는 여러 방법이 표시되는데, 그 중 세션 매니저(Session Manager)를 선택합니다. 이 후 안내를 따라 인스턴스 내부에 접속합니다. diff --git a/examples/blueprint/apps/README.md b/examples/blueprint/apps/README.md index cb384b4..113acb9 100644 --- a/examples/blueprint/apps/README.md +++ b/examples/blueprint/apps/README.md @@ -46,5 +46,22 @@ Launching a new EC2 instance into warm pool: i-0180961b460339ed3 Duration: 215s ![aws-asg-activity-history](../../../images/aws-asg-activity-history.png) -### Connect -Move to the EC2 service page on the AWS Management Conosol and select Instances button on the left side menu. Find an instance that you launched. Select the instance and click 'Connect' button on top of the window. After then you will see three tabs EC2 Instance Connect, Session Manager, SSH client. Select Session Manager tab and follow the instruction on the screen. +## AWS Systems Manager Documents +### Run command +You can use Run Command, a capability of AWS Systems Manager, from the console to configure instances without having to log in to each instance. + +**To send a command using Run Command** + +1. Open the AWS Systems Manager console at https://console.aws.amazon.com/systems-manager/. +1. In the navigation pane, choose Run Command. Or if the AWS Systems Manager home page opens first, choose the menu icon (stacked three bars) to open the navigation pane, and then choose *Run Command*. +1. Choose *Run command*. +1. In the Command document list, choose a Systems Manager document. +1. In the Command parameters section, specify values for required parameters. +1. In the Targets section, identify the instances on which you want to run this operation by specifying tags, selecting instances manually, or specifying a resource group. +1. For Other parameters: + * For Comment, enter information about this command. + * For Timeout (seconds), specify the number of seconds for the system to wait before failing the overall command execution. +1. For Rate control: + * For Concurrency, specify either a number or a percentage of instances on which to run the command at the same time. +1. (Optional) For Output options, to save the command output to a file, select the Write command output to an S3 bucket box. Enter the bucket and prefix (folder) names in the boxes. +1. Choose *Run*. diff --git a/examples/ssm-document/templates/cwagent.yaml b/examples/blueprint/apps/documents/cwagent.yaml similarity index 100% rename from examples/ssm-document/templates/cwagent.yaml rename to examples/blueprint/apps/documents/cwagent.yaml diff --git a/examples/ssm-document/templates/diskfull.yaml b/examples/blueprint/apps/documents/diskfull.yaml similarity index 100% rename from examples/ssm-document/templates/diskfull.yaml rename to examples/blueprint/apps/documents/diskfull.yaml diff --git a/examples/ssm-document/templates/envoy.yaml b/examples/blueprint/apps/documents/envoy.yaml similarity index 100% rename from examples/ssm-document/templates/envoy.yaml rename to examples/blueprint/apps/documents/envoy.yaml diff --git a/examples/blueprint/main.tf b/examples/blueprint/main.tf index fc3f790..f9a57b0 100644 --- a/examples/blueprint/main.tf +++ b/examples/blueprint/main.tf @@ -50,6 +50,34 @@ resource "aws_eip" "eip" { } } +### security/policy +resource "aws_iam_policy" "eip" { + name = "eip-auto-reassociation-policy" + tags = var.tags + policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Action = [ + "ec2:DescribeTags", + "ec2:AssociateAddress", + ] + Effect = "Allow" + Resource = ["*"] + }, ] + }) +} + +### application/script +locals { + httpd = join("\n", [ + "sudo yum update -y", + "sudo yum install -y httpd", + "sudo rm /etc/httpd/conf.d/welcome.conf", + "sudo systemctl start httpd", + ] + ) +} + ### compute module "ec2" { source = "Young-ook/ssm/aws" @@ -59,7 +87,10 @@ module "ec2" { node_groups = [ { name = "bastion" + tags = merge(var.tags, { env = "dev" }) desired_size = 1 + min_size = 1 + max_size = 1 instance_type = "t3.medium" ami_type = "AL2_x86_64" policy_arns = [ @@ -68,11 +99,11 @@ module "ec2" { }, { name = "eip" + tags = merge({ eipAllocId = aws_eip.eip.id }) desired_size = 1 min_size = 1 max_size = 1 instance_type = "t3.small" - tags = merge({ eipAllocId = aws_eip.eip.id }) user_data = file("${path.module}/apps/eip/eip.tpl") policy_arns = [aws_iam_policy.eip.arn] }, @@ -108,11 +139,23 @@ module "ec2" { max_group_prepared_capacity = 2 pool_state = "Stopped" } - } + }, + { + name = "envoy" + tags = merge(var.tags, { envoy = "enabled" }) + desired_size = 1 + instance_type = "t3.small" + ami_type = "AL2_x86_64" + user_data = local.httpd + policy_arns = [ + "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy", + "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" + ] + }, ] } -# lifecycle hook complete signal policy +### lifecycle hook complete signal policy resource "aws_iam_policy" "lc" { name = "warmpools-lifecycle-hook-action" tags = var.tags @@ -148,19 +191,73 @@ resource "local_file" "elapsedtime" { file_permission = "0500" } -### security/policy -resource "aws_iam_policy" "eip" { - name = "eip-auto-reassociation-policy" - tags = var.tags - policy = jsonencode({ - Version = "2012-10-17" - Statement = [{ - Action = [ - "ec2:DescribeTags", - "ec2:AssociateAddress", - ] - Effect = "Allow" - Resource = ["*"] - }, ] - }) +### governence/automation +resource "aws_ssm_document" "diskfull" { + name = "Run-Disk-Stress" + document_format = "YAML" + document_type = "Command" + content = file("${path.module}/apps/documents/diskfull.yaml") +} + +resource "aws_ssm_document" "cwagent" { + name = "Install-CloudWatch-Agent" + document_format = "YAML" + document_type = "Command" + content = file("${path.module}/apps/documents/cwagent.yaml") +} + +resource "aws_ssm_document" "envoy" { + name = "Install-EnvoyProxy" + document_format = "YAML" + document_type = "Command" + content = file("${path.module}/apps/documents/envoy.yaml") +} + +resource "aws_ssm_association" "cwagent" { + for_each = toset(lookup(var.automation, "cwagent", false) ? ["enabled"] : []) + name = aws_ssm_document.cwagent.name + association_name = "Install-CloudWatchAgent" + targets { + key = "tag:env" + values = ["dev"] + } +} + +resource "time_sleep" "wait" { + depends_on = [aws_ssm_association.cwagent] + create_duration = "15s" +} + +resource "aws_ssm_association" "diskfull" { + for_each = toset(lookup(var.automation, "diskfull", false) ? ["enabled"] : []) + depends_on = [time_sleep.wait] + name = aws_ssm_document.diskfull.name + association_name = "Run-Disk-Stress-Test" + parameters = { + DurationSeconds = "60" + Workers = "4" + Percent = "70" + } + targets { + key = "tag:env" + values = ["dev"] + } +} + +resource "aws_ssm_association" "envoy" { + for_each = toset(lookup(var.automation, "envoy", false) ? ["enabled"] : []) + depends_on = [time_sleep.wait] + name = aws_ssm_document.envoy.name + association_name = "Install-EnvoyProxy" + parameters = { + region = var.aws_region + mesh = "app" + vnode = "service" + envoyVersion = "v1.23.1.0" + appPort = "80" + } + targets { + key = "tag:envoy" + values = ["enabled"] + } } diff --git a/examples/blueprint/outputs.tf b/examples/blueprint/outputs.tf index 8dfd197..faa53af 100644 --- a/examples/blueprint/outputs.tf +++ b/examples/blueprint/outputs.tf @@ -2,3 +2,12 @@ output "ec2" { description = "The generated AWS EC2 autoscaling groups" value = module.ec2.cluster.data_plane } + +output "ssm-doc" { + description = "The generated AWS Systems Manager Documents" + value = { + diskfull = aws_ssm_document.diskfull.arn + cwagent = aws_ssm_document.cwagent.arn + envoy = aws_ssm_document.envoy.arn + } +} diff --git a/examples/blueprint/variables.tf b/examples/blueprint/variables.tf index 70ca83a..64125c1 100644 --- a/examples/blueprint/variables.tf +++ b/examples/blueprint/variables.tf @@ -25,6 +25,17 @@ variable "node_groups" { default = [] } +### features +variable "automation" { + description = "Feature toggles for ec2 management automation" + type = map(bool) + default = { + diskfull = false + cwagent = true + envoy = true + } +} + ### description variable "name" { description = "The logical name of the module instance" diff --git a/examples/ssm-document/README.md b/examples/ssm-document/README.md deleted file mode 100644 index 91b9fc8..0000000 --- a/examples/ssm-document/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# AWS Systems Manager Document - -## Download example -Download this example on your workspace -```sh -git clone https://github.com/Young-ook/terraform-aws-ssm -cd terraform-aws-ssm/examples/ssm-document -``` - -## Setup -[This](https://github.com/Young-ook/terraform-aws-ssm/blob/main/examples/ssm-document/main.tf) is the example of terraform configuration file to create an EC2 instance which is managed by Systems Manager on your AWS account. Check out and apply it using terraform command. - -If you don't have the terraform tools in your environment, go to the main [page](https://github.com/Young-ook/terraform-aws-ssm#terraform) of this repository and follow the installation instructions. - -Run terraform: -``` -terraform init -terraform apply -``` -Also you can use the `-var-file` option for customized paramters when you run the terraform plan/apply command. -``` -terraform plan -var-file tc1.tfvars -terraform apply -var-file tc1.tfvars -``` - -## Run command -You can use Run Command, a capability of AWS Systems Manager, from the console to configure instances without having to log in to each instance. - -**To send a command using Run Command** - -1. Open the AWS Systems Manager console at https://console.aws.amazon.com/systems-manager/. -1. In the navigation pane, choose Run Command. Or if the AWS Systems Manager home page opens first, choose the menu icon (stacked three bars) to open the navigation pane, and then choose *Run Command*. -1. Choose *Run command*. -1. In the Command document list, choose a Systems Manager document. -1. In the Command parameters section, specify values for required parameters. -1. In the Targets section, identify the instances on which you want to run this operation by specifying tags, selecting instances manually, or specifying a resource group. -1. For Other parameters: - * For Comment, enter information about this command. - * For Timeout (seconds), specify the number of seconds for the system to wait before failing the overall command execution. -1. For Rate control: - * For Concurrency, specify either a number or a percentage of instances on which to run the command at the same time. -1. (Optional) For Output options, to save the command output to a file, select the Write command output to an S3 bucket box. Enter the bucket and prefix (folder) names in the boxes. -1. Choose *Run*. - -## Connect -Move to the EC2 service page on the AWS Management Conosol and select Instances button on the left side menu. Find an instance that you launched. Select the instance and click *Connect* button on top of the window. After then you will see three tabs EC2 Instance Connect, Session Manager, SSH client. Select Session Manager tab and follow the instruction on the screen. - -![aws-fis-ec2-disk-stress](../../images/aws-fis-ec2-disk-stress.png) - -## Clean up -Run terraform: -``` -terraform destroy -``` -Don't forget you have to use the `-var-file` option when you run terraform destroy command to delete the aws resources created with extra variable files. -``` -terraform destroy -var-file tc1.tfvars -``` diff --git a/examples/ssm-document/default.auto.tfvars b/examples/ssm-document/default.auto.tfvars deleted file mode 100644 index 358fa5a..0000000 --- a/examples/ssm-document/default.auto.tfvars +++ /dev/null @@ -1,5 +0,0 @@ -name = "ssm-doc" -tags = { - env = "dev" -} -aws_region = "ap-northeast-2" diff --git a/examples/ssm-document/main.tf b/examples/ssm-document/main.tf deleted file mode 100644 index 615f796..0000000 --- a/examples/ssm-document/main.tf +++ /dev/null @@ -1,128 +0,0 @@ -# AWS Systems Manager Document example - -terraform { - required_version = "~> 1.0" - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 3.71" - } - } -} - -provider "aws" { - region = var.aws_region -} - -### network/vpc (default vpc) -module "vpc" { - source = "Young-ook/vpc/aws" - version = "1.0.1" - name = var.name - tags = var.tags -} - -### ec2 -module "ec2" { - source = "Young-ook/ssm/aws" - version = "1.0.3" - name = var.name - tags = var.tags - subnets = values(module.vpc.subnets["public"]) - node_groups = [ - { - name = "default" - tags = merge(var.tags, { envoy = "enabled" }) - desired_size = 1 - instance_type = "t3.small" - ami_type = "AL2_x86_64" - user_data = local.server - policy_arns = [ - "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy", - "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" - ] - }, - ] -} - -### application/script -locals { - server = join("\n", [ - "sudo yum update -y", - "sudo yum install -y httpd", - "sudo rm /etc/httpd/conf.d/welcome.conf", - "sudo systemctl start httpd", - ] - ) -} - -### management/document (playbook) -resource "aws_ssm_document" "diskfull" { - name = "Run-Disk-Stress" - document_format = "YAML" - document_type = "Command" - content = file("${path.module}/templates/diskfull.yaml") -} - -resource "aws_ssm_document" "cwagent" { - name = "Install-CloudWatch-Agent" - document_format = "YAML" - document_type = "Command" - content = file("${path.module}/templates/cwagent.yaml") -} - -resource "aws_ssm_document" "envoy" { - name = "Install-EnvoyProxy" - document_format = "YAML" - document_type = "Command" - content = file(join("/", [path.module, "templates", "envoy.yaml"])) -} - -resource "aws_ssm_association" "cwagent" { - for_each = toset(lookup(var.features, "cwagent", false) ? ["enabled"] : []) - name = aws_ssm_document.cwagent.name - association_name = "Install-CloudWatchAgent" - targets { - key = "tag:env" - values = ["dev"] - } -} - -resource "time_sleep" "wait" { - depends_on = [aws_ssm_association.cwagent] - create_duration = "15s" -} - -resource "aws_ssm_association" "diskfull" { - for_each = toset(lookup(var.features, "diskfull", false) ? ["enabled"] : []) - depends_on = [time_sleep.wait] - name = aws_ssm_document.diskfull.name - association_name = "Run-Disk-Stress-Test" - parameters = { - DurationSeconds = "60" - Workers = "4" - Percent = "70" - } - targets { - key = "tag:env" - values = ["dev"] - } -} - -resource "aws_ssm_association" "envoy" { - for_each = toset(lookup(var.features, "envoy", false) ? ["enabled"] : []) - depends_on = [time_sleep.wait] - name = aws_ssm_document.envoy.name - association_name = "Install-EnvoyProxy" - parameters = { - region = var.aws_region - mesh = "app" - vnode = "service" - envoyVersion = "v1.23.1.0" - appPort = "80" - } - targets { - key = "tag:envoy" - values = ["enabled"] - } -} diff --git a/examples/ssm-document/outputs.tf b/examples/ssm-document/outputs.tf deleted file mode 100644 index f50dab4..0000000 --- a/examples/ssm-document/outputs.tf +++ /dev/null @@ -1,13 +0,0 @@ -output "ec2" { - description = "The generated AWS EC2 autoscaling group" - value = module.ec2.cluster -} - -output "ssm-doc" { - description = "The generated AWS Systems Manager Documents" - value = { - diskfull = aws_ssm_document.diskfull.arn - cwagent = aws_ssm_document.cwagent.arn - envoy = aws_ssm_document.envoy.arn - } -} diff --git a/examples/ssm-document/variables.tf b/examples/ssm-document/variables.tf deleted file mode 100644 index 80615cd..0000000 --- a/examples/ssm-document/variables.tf +++ /dev/null @@ -1,39 +0,0 @@ -# Variables for providing to module fixture codes - -### features -variable "features" { - description = "Feature toggle options" - type = map(bool) - default = { - diskfull = true - cwagent = true - envoy = true - } -} - -### network -variable "aws_region" { - description = "The aws region to deploy" - type = string - default = "us-east-1" -} - -### compute -variable "node_groups" { - description = "Node groups definition" - default = [] -} - -### description -variable "name" { - description = "The logical name of the module instance" - type = string - default = "ssm" -} - -### tags -variable "tags" { - description = "The key-value maps for tagging" - type = map(string) - default = {} -}