├── .circleci └── config.yml ├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .terraform-version ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── examples ├── basic_usage.tf ├── custom_ami.tf ├── custom_cw_config.tf └── text │ └── linux_cw_agent_param.json ├── main.tf ├── outputs.tf ├── tests └── test1 │ ├── main.tf │ └── variables.tf ├── text ├── amazon_linux_userdata.sh ├── debian_userdata.sh ├── linux_cw_agent_param.json ├── rhel_centos_7_userdata.sh ├── rhel_centos_8_userdata.sh ├── ubuntu_userdata.sh ├── windows_cw_agent_param.json └── windows_userdata.ps1 └── variables.tf /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | test: 4 | docker: 5 | - image: 891714082543.dkr.ecr.us-west-2.amazonaws.com/rackspace-tf-toolbox 6 | working_directory: ~/ 7 | steps: 8 | - attach_workspace: 9 | at: ~/workspace 10 | - checkout: 11 | path: ~/branches/${CIRCLE_BRANCH} 12 | - run: 13 | name: Run Test 14 | command: MODULE_CI_JOB='test' python3 orchestrate.py 15 | - run: 16 | name: destroy 17 | command: cd ~ && ~/bin/destroy.sh && ~/bin/destroy_s3_buckets.sh # must succeed or we have something to clean up manually 18 | when: always 19 | - persist_to_workspace: 20 | root: ~/workspace 21 | paths: 22 | - plan_results/* 23 | - artifacts/* 24 | check_destruction: 25 | docker: 26 | - image: 891714082543.dkr.ecr.us-west-2.amazonaws.com/rackspace-tf-toolbox 27 | working_directory: ~/ 28 | steps: 29 | - attach_workspace: 30 | at: ~/workspace 31 | - checkout: 32 | path: ~/module 33 | - run: 34 | name: Check Destruction 35 | command: MODULE_CI_JOB='check_destruction' python3 orchestrate.py 36 | - store_artifacts: 37 | path: ~/workspace/artifacts 38 | 39 | 40 | workflows: 41 | version: 2 42 | build_and_test: 43 | jobs: 44 | - test: 45 | filters: 46 | branches: 47 | ignore: master 48 | - check_destruction: 49 | requires: 50 | - test 51 | filters: 52 | branches: 53 | ignore: master 54 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ##### Corresponding Issue(s): 2 | - PRs should have a corresponding issue. If no issue exists, provide details in the **Reason for Change(s)** section 3 | 4 | ##### Summary of change(s): 5 | 6 | ##### Reason for Change(s): 7 | 8 | - If a bug, describe error scenario, including expected behavior and actual behavior. 9 | 10 | - If an enhancement, describe the use case and the perceived benefit(s). 11 | 12 | ##### Will the change trigger resource destruction or replacement? If yes, please provide justification: 13 | 14 | ##### Does this update/change involve issues with other external modules? If so, please describe the scenario. 15 | 16 | ##### If input variables or output variables have changed or has been added, have you updated the README? 17 | 18 | ##### Do examples need to be updated based on changes? 19 | 20 | ##### Note to the PR requester about Closing PR's 21 | Please message the person that opened the issue when auto closing it on slack, as well as any other stake holders of deep interest. Only close the issue if you believe that the issue is fully resolved with this PR. 22 | 23 | #### This PR may auto close the issue associated with it. If you feel the issue is not resolved please reopen the issue. 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # .tfvars files 9 | *.tfvars 10 | 11 | # Plans 12 | *.plans 13 | 14 | # Secrets 15 | secrets.tf 16 | 17 | # Mac 18 | .DS_Store 19 | 20 | # Idea 21 | .idea/* -------------------------------------------------------------------------------- /.terraform-version: -------------------------------------------------------------------------------- 1 | 1.0.0 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | This document is a set of guidelines to contribute to the [Rackspace](https://www.rackspace.com) [Terraform](https://www.terraform.io/) modules. These modules were created to enable and empower our Managed Infrastructure as Code product. While these modules are designed for Rackspace environments, we hope they may be of use to the community at large. 4 | 5 | ## Reporting issues 6 | 7 | Rackspace customers should open a normal Rackspace support ticket to report any problems or feedback for these modules. Our support Rackers will then work with you and our product team to address those issues. 8 | 9 | ## Submitting Changes 10 | 11 | Pull requests are welcome. Currently our CI solution cannot run against pull requests from forks. Despite this, these submissions are still welcome. All pull requests will be evaluated against Rackspace best practices, and after approval, will be migrated to a branch for testing. 12 | 13 | For significant or critical features, a new test should be created, or if appropriate, and existing test should be updated. This will serve to ensure the any failures related to the feature are caught. 14 | 15 | When submitting a pull request please explain the changes in detail, and try to minimize the scope to related changes. For example, changes resolving separate bugs should be broken out into separate pull requests. If there are relevant documentation or references, such as terraform bug reports, links to those references are greatly appreciated. 16 | 17 | ## Testing 18 | 19 | Pull requests must pass a linting and build test prior to acceptance. This test ensures all submissions will produce a stable and working deployment. In addition, our CI jobs will run a check_destruction test to help determine if any breaking changes will occur with this change. This test will show a failed result if breaking changes are detected, but this will not prevent the submission from being approved. 20 | 21 | ## Coding and Style guidelines 22 | 23 | All submissions should comply with the coding and style guides outlined at [General Terraform Style Guide](https://manage.rackspace.com/aws/docs/product-guide/miac/terraform-standards.html#general-terraform-style-guide) and [Rackspace Module Standards](https://manage.rackspace.com/aws/docs/product-guide/miac/terraform-standards.html#rackspace-module-). CI testing will run and flag code that does not meet these defined standards whenever possible. 24 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2018 Rackspace, Inc. 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!CAUTION] 2 | > This project is end of life. This repo will be deleted on June 2nd 2025. 3 | 4 | # aws-terraform-ec2\_asg 5 | 6 | This module creates one or more autoscaling groups. 7 | 8 | ## Basic Usage 9 | 10 | ```HCL 11 | module "asg" { 12 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-ec2_asg//?ref=v0.12.16" 13 | 14 | ec2_os = "amazon2" 15 | name = "my_asg" 16 | security_groups = [module.sg.private_web_security_group_id] 17 | subnets = module.vpc.private_subnets 18 | } 19 | ``` 20 | 21 | Full working references are available at [examples](examples) 22 | 23 | ## Other TF Modules Used 24 | 25 | Using [aws-terraform-cloudwatch\_alarm](https://github.com/rackspace-infrastructure-automation/aws-terraform-cloudwatch_alarm) to create the following CloudWatch Alarms: 26 | - group\_terminating\_instances 27 | 28 | ## Terraform 0.12 upgrade 29 | 30 | Several changes were required while adding terraform 0.12 compatibility. The following changes should 31 | made when upgrading from a previous release to version 0.12.0 or higher. 32 | 33 | ### Module variables 34 | 35 | The following module variables were updated to better meet current Rackspace style guides: 36 | 37 | - `security_group_list` -> `security_groups` 38 | - `resource_name` -> `name` 39 | 40 | The following variables are no longer neccessary and were removed 41 | 42 | - `additional_ssm_bootstrap_step_count` 43 | - `install_scaleft_agent` 44 | 45 | Several new variables were introduced to provide existing functionality, with a simplified format. The original formmating was also retained to allow easier transition. 46 | 47 | New variables `tags` and `tags_asg` were added to replace the functionality of the `additional_tags` variable. `tags` allows setting tags on all resources, while `tags_asg` sets tags only on the ASG itself. `additional_tags` will continue to work as expected, but will be removed in a future release. 48 | 49 | New variable `ssm_bootstrap_list` was added to allow setting the SSM association steps using objects instead of strings, allowing easier linting and formatting of these lines. The `additional_ssm_bootstrap_list` variable will continue to work, but will be deprecated in a future release. 50 | 51 | ## Requirements 52 | 53 | | Name | Version | 54 | |------|---------| 55 | | terraform | >= 1.0.0 | 56 | | aws | ~> 3.0 | 57 | 58 | ## Providers 59 | 60 | | Name | Version | 61 | |------|---------| 62 | | aws | ~> 3.0 | 63 | 64 | ## Modules 65 | 66 | | Name | Source | Version | 67 | |------|--------|---------| 68 | | group_terminating_instances | git@github.com:rackspace-infrastructure-automation/aws-terraform-cloudwatch_alarm//?ref=v0.12.6 | | 69 | 70 | ## Resources 71 | 72 | | Name | 73 | |------| 74 | | [aws_ami](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/data-sources/ami) | 75 | | [aws_autoscaling_group](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/resources/autoscaling_group) | 76 | | [aws_autoscaling_notification](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/resources/autoscaling_notification) | 77 | | [aws_autoscaling_policy](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/resources/autoscaling_policy) | 78 | | [aws_caller_identity](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/data-sources/caller_identity) | 79 | | [aws_cloudwatch_log_group](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/resources/cloudwatch_log_group) | 80 | | [aws_cloudwatch_metric_alarm](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/resources/cloudwatch_metric_alarm) | 81 | | [aws_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/resources/iam_instance_profile) | 82 | | [aws_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/resources/iam_policy) | 83 | | [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/data-sources/iam_policy_document) | 84 | | [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/resources/iam_role) | 85 | | [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/resources/iam_role_policy_attachment) | 86 | | [aws_launch_template](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/resources/launch_template) | 87 | | [aws_region](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/data-sources/region) | 88 | | [aws_ssm_association](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/resources/ssm_association) | 89 | | [aws_ssm_document](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/resources/ssm_document) | 90 | | [aws_ssm_parameter](https://registry.terraform.io/providers/hashicorp/aws/3.0/docs/resources/ssm_parameter) | 91 | 92 | ## Inputs 93 | 94 | | Name | Description | Type | Default | Required | 95 | |------|-------------|------|---------|:--------:| 96 | | additional\_ssm\_bootstrap\_list | A list of maps consisting of main step actions, to be appended to SSM associations. Please see usage.tf.example in this repo for examples.

(DEPRECATED) This variable will be removed in future releases in favor of the `ssm_bootstrap_list` variable. | `list(map(string))` | `[]` | no | 97 | | additional\_tags | Additional tags to be added to the ASG instance(s). Format: list of maps. Please see usage.tf.example in this repo for examples.

(DEPRECATED) This variable will be removed in future releases in favor of the `tags` and `tags_asg` variables. | `list(map(string))` | `[]` | no | 98 | | alb\_resource\_label | Enter the ALB and Target group in this format : app/load-balancer-name/load-balancer-id/targetgroup/target-group-name/target-group-id | `string` | `null` | no | 99 | | asg\_count | Number of identical ASG's to deploy | `string` | `"1"` | no | 100 | | asg\_wait\_for\_capacity\_timeout | A maximum duration that Terraform should wait for ASG instances to be healthy before timing out. | `string` | `"10m"` | no | 101 | | backup\_tag\_value | Value of the 'Backup' tag, used to assign to the AWS Backup configuration | `string` | `"False"` | no | 102 | | cloudwatch\_log\_retention | The number of days to retain Cloudwatch Logs for this instance. | `string` | `"30"` | no | 103 | | custom\_cw\_agent\_config\_ssm\_param | SSM Parameter Store name that contains a custom CloudWatch agent configuration that you would like to use as an alternative to the default provided. | `string` | `""` | no | 104 | | customer\_alarms\_cleared | Specifies whether alarms will notify customers when returning to an OK status. | `bool` | `false` | no | 105 | | customer\_alarms\_enabled | Specifies whether alarms will notify customers. Automatically enabled if rackspace\_managed is set to false | `bool` | `false` | no | 106 | | cw\_high\_evaluations | The number of periods over which data is compared to the specified threshold. | `string` | `"3"` | no | 107 | | cw\_high\_operator | Math operator used by CloudWatch for alarms and triggers. | `string` | `"GreaterThanThreshold"` | no | 108 | | cw\_high\_period | Time the specified statistic is applied. Must be in seconds that is also a multiple of 60. | `string` | `"60"` | no | 109 | | cw\_high\_threshold | The value against which the specified statistic is compared. | `string` | `"60"` | no | 110 | | cw\_low\_evaluations | The number of periods over which data is compared to the specified threshold. | `string` | `"3"` | no | 111 | | cw\_low\_operator | Math operator used by CloudWatch for alarms and triggers. | `string` | `"LessThanThreshold"` | no | 112 | | cw\_low\_period | Time the specified statistic is applied. Must be in seconds that is also a multiple of 60. | `string` | `"300"` | no | 113 | | cw\_low\_threshold | The value against which the specified statistic is compared. | `string` | `"30"` | no | 114 | | cw\_scaling\_metric | The metric to be used for scaling. | `string` | `"CPUUtilization"` | no | 115 | | detailed\_monitoring | Enable Detailed Monitoring? true or false | `bool` | `true` | no | 116 | | disable\_scale\_in | Disable scale in to create only a scale-out policy in Target Tracking Policy. | `bool` | `false` | no | 117 | | ec2\_os | Intended Operating System/Distribution of Instance. Valid inputs are: `amazon2`, `amazoneks`, `amazonecs`, `rhel7`, `rhel8`, `centos7`, `ubuntu18`, `ubuntu20`, `windows2012r2`, `windows2016`, `windows2019` | `string` | n/a | yes | 118 | | ec2\_scale\_down\_adjustment | Number of EC2 instances to scale down by at a time. Positive numbers will be converted to negative. | `string` | `"-1"` | no | 119 | | ec2\_scale\_down\_cool\_down | Time in seconds before any further trigger-related scaling can occur. | `string` | `"60"` | no | 120 | | ec2\_scale\_up\_adjustment | Number of EC2 instances to scale up by at a time. | `string` | `"1"` | no | 121 | | ec2\_scale\_up\_cool\_down | Time in seconds before any further trigger-related scaling can occur. | `string` | `"60"` | no | 122 | | enable\_ebs\_optimization | Use EBS Optimized? true or false | `bool` | `false` | no | 123 | | enable\_rolling\_updates | Should this autoscaling group be targeted by the ASG Instance Replacement tool to ensure all instances are using thelatest launch configuration. | `bool` | `true` | no | 124 | | enable\_scaling\_actions | Should this autoscaling group be configured with scaling alarms to manage the desired count. Set this variable to false if another process will manage the desired count, such as EKS Cluster Autoscaler. | `bool` | `true` | no | 125 | | enable\_scaling\_notification | true or false. If 'scaling\_notification\_topic' is set to a non-empty string, this must be set to true. Otherwise, set to false. This variable exists due to a terraform limitation with using count and computed values as conditionals | `bool` | `false` | no | 126 | | enabled\_asg\_metrics | List of ASG metrics desired. This can only contain the following values: `GroupDesiredCapacity`, `GroupInServiceCapacity`, `GroupPendingCapacity`, `GroupMinSize`, `GroupMaxSize`, `GroupInServiceInstances`, `GroupPendingInstances`, `GroupStandbyInstances`, `GroupStandbyCapacity`, `GroupTerminatingCapacity`, `GroupTerminatingInstances`, `GroupTotalCapacity`, `GroupTotalInstances`. | `list(string)` | `[]` | no | 127 | | encrypt\_primary\_ebs\_volume | Encrypt root EBS Volume? true or false | `bool` | `false` | no | 128 | | encrypt\_secondary\_ebs\_volume | Encrypt secondary EBS Volume? true or false | `bool` | `false` | no | 129 | | environment | Application environment for which this network is being created. Preferred value are Development, Integration, PreProduction, Production, QA, Staging, or Test | `string` | `"Development"` | no | 130 | | final\_userdata\_commands | Commands to be given at the end of userdata for an instance. This should generally not include bootstrapping or ssm install. | `string` | `""` | no | 131 | | health\_check\_grace\_period | Number of seconds grace during which no autoscaling actions will be taken. | `string` | `"300"` | no | 132 | | health\_check\_type | Define the type of healthcheck for the AutoScaling group. | `string` | `"EC2"` | no | 133 | | image\_id | The AMI ID to be used to build the EC2 Instance. If not provided, an AMI ID will be queried with an OS specified in variable ec2\_os. | `string` | `""` | no | 134 | | initial\_userdata\_commands | Commands to be given at the start of userdata for an instance. This should generally not include bootstrapping or ssm install. | `string` | `""` | no | 135 | | install\_codedeploy\_agent | Install codedeploy agent on instance(s)? true or false | `bool` | `false` | no | 136 | | instance\_profile\_override | Optionally provide an instance profile. Any override profile should contain the permissions required for Rackspace support tooling to continue to function if required. | `bool` | `false` | no | 137 | | instance\_profile\_override\_name | Provide an instance profile name. Any override profile should contain the permissions required for Rackspace support tooling to continue to function if required. To use this set `instance_profile_override` to `true`. | `string` | `""` | no | 138 | | instance\_role\_managed\_policy\_arn\_count | The number of policy ARNs provided/set in variable 'instance\_role\_managed\_policy\_arns' | `string` | `"0"` | no | 139 | | instance\_role\_managed\_policy\_arns | List of IAM policy ARNs for the InstanceRole IAM role. IAM ARNs can be found within the Policies section of the AWS IAM console. e.g. ['arn:aws:iam::aws:policy/AmazonEC2FullAccess', 'arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore', 'arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetRole'] | `list(string)` | `[]` | no | 140 | | instance\_type | EC2 Instance Type e.g. 't2.micro' | `string` | `"t2.micro"` | no | 141 | | instance\_warm\_up\_time | Specify the Instance Warm Up time for Target Tracking Policy. | `string` | `"300"` | no | 142 | | key\_pair | Name of an existing EC2 KeyPair to enable SSH access to the instances. | `string` | `""` | no | 143 | | load\_balancer\_names | A list of Classic load balancers associated with this Auto Scaling group. | `list(string)` | `[]` | no | 144 | | metadata\_http\_endpoint | Whether the metadata service is available. Valid values include enabled or disabled. | `string` | `"enabled"` | no | 145 | | metadata\_http\_put\_response\_hop\_limit | Desired HTTP PUT response hop limit for instance metadata requests. The larger the number, the further instance metadata requests can travel. Valid values are integer from 1 to 64 | `number` | `1` | no | 146 | | metadata\_http\_tokens | Whether or not the metadata service requires session tokens, also referred to as Instance Metadata Service Version 2 (IMDSv2). Valid values include optional or required. | `string` | `"optional"` | no | 147 | | metadata\_instance\_metadata\_tags | Enables or disables access to instance tags from the instance metadata service. Valid values include enabled or disabled | `string` | `"disabled"` | no | 148 | | name | Name to be used for the provisioned EC2 instance(s), ASG(s), and other resources provisioned in this module | `string` | n/a | yes | 149 | | notification\_topic | List of SNS Topic ARNs to use for customer notifications. | `list(string)` | `[]` | no | 150 | | perform\_ssm\_inventory\_tag | Determines whether Instance is tracked via System Manager Inventory. | `string` | `"True"` | no | 151 | | policy\_type | Enter scaling policy type. Allowed values are : SimpleScaling or TargetTrackingScaling | `string` | `"SimpleScaling"` | no | 152 | | primary\_ebs\_volume\_iops | Iops value required for use with io1 EBS volumes. This value should be 3 times the EBS volume size | `string` | `"0"` | no | 153 | | primary\_ebs\_volume\_size | EBS Volume Size in GB | `string` | `"60"` | no | 154 | | primary\_ebs\_volume\_type | EBS Volume Type. e.g. gp2, io1, st1, sc1 | `string` | `"gp2"` | no | 155 | | provide\_custom\_cw\_agent\_config | Set to true if a custom cloudwatch agent configuration has been provided in variable custom\_cw\_agent\_config\_ssm\_param. | `bool` | `false` | no | 156 | | rackspace\_alarms\_enabled | Specifies whether alarms will create a Rackspace ticket. Ignored if rackspace\_managed is set to false. | `bool` | `false` | no | 157 | | rackspace\_managed | Boolean parameter controlling if instance will be fully managed by Rackspace support teams, created CloudWatch alarms that generate tickets, and utilize Rackspace managed SSM documents. | `bool` | `true` | no | 158 | | scaling\_max | The maximum size of the Auto Scaling group. | `string` | `"2"` | no | 159 | | scaling\_min | The minimum count of EC2 instances in the Auto Scaling group. | `string` | `"1"` | no | 160 | | scaling\_notification\_topic | SNS Topic ARN to notify if there are any scaling operations. OPTIONAL | `string` | `""` | no | 161 | | secondary\_ebs\_volume\_existing\_id | The Snapshot ID of an existing EBS volume you want to use for the secondary volume. i.e. snap-0ad8580e3ac34a9f1 | `string` | `""` | no | 162 | | secondary\_ebs\_volume\_iops | Iops value required for use with io1 EBS volumes. This value should be 3 times the EBS volume size | `string` | `"0"` | no | 163 | | secondary\_ebs\_volume\_size | EBS Volume Size in GB | `string` | `""` | no | 164 | | secondary\_ebs\_volume\_type | EBS Volume Type. e.g. gp2, io1, st1, sc1 | `string` | `"gp2"` | no | 165 | | security\_groups | A list of EC2 security IDs to assign to this resource. | `list(string)` | n/a | yes | 166 | | ssm\_association\_refresh\_rate | A cron or rate pattern to define the SSM Association refresh schedule, defaulting to once per day. See https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-cron.html for more details. Schedule can be disabled by providing an empty string. | `string` | `"rate(1 day)"` | no | 167 | | ssm\_bootstrap\_list | A list of objects consisting of actions, to be appended to SSM associations. Please see usage.tf.example in this repo for examples. | `any` | `[]` | no | 168 | | ssm\_patching\_group | Group ID to be used by System Manager for Patching | `string` | `""` | no | 169 | | subnets | List of subnets for Application. e.g. ['subnet-8da92df7', 'subnet-9e5dc5f6', 'subnet-497eaf33'] | `list(string)` | n/a | yes | 170 | | tags | A map of tags to apply to all resources. These tags will all be propagated to ASG instances and set on all other resources. | `map(string)` | `{}` | no | 171 | | tags\_asg | A map of tags to apply to the ASG itself. These tags will not be propagated to ASG instances or set on any other resources. | `map(string)` | `{}` | no | 172 | | target\_group\_arns | A list of Amazon Resource Names (ARN) of target groups to associate with the Auto Scaling group. | `list(string)` | `[]` | no | 173 | | target\_value | Enter the target value for Target Scaling Policy metrics. | `string` | `"50"` | no | 174 | | tenancy | The placement tenancy for EC2 devices. e.g. host, default, dedicated | `string` | `"default"` | no | 175 | | terminated\_instances | Specifies the maximum number of instances that can be terminated in a six hour period without generating a Cloudwatch Alarm. | `string` | `"30"` | no | 176 | | tracking\_policy\_metric | Allowed Values are: ASGAverageCPUUtilization, ASGAverageNetworkIn, ASGAverageNetworkOut, ALBRequestCountPerTarget | `string` | `"ASGAverageCPUUtilization"` | no | 177 | 178 | ## Outputs 179 | 180 | | Name | Description | 181 | |------|-------------| 182 | | asg\_arn\_list | List of ASG ARNs | 183 | | asg\_image\_id | Image ID used for EC2 provisioning | 184 | | asg\_name\_list | List of ASG names | 185 | | iam\_role | Name of the created IAM Instance role. | 186 | -------------------------------------------------------------------------------- /examples/basic_usage.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | } 4 | 5 | provider "aws" { 6 | version = "~> 3.0" 7 | region = "us-west-2" 8 | } 9 | 10 | resource "random_string" "name_rstring" { 11 | length = 8 12 | special = false 13 | } 14 | 15 | module "vpc" { 16 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-vpc_basenetwork?ref=v0.12.7" 17 | 18 | name = "${random_string.name_rstring.result}-ec2-asg-basenetwork-example" 19 | } 20 | 21 | data "aws_region" "current_region" {} 22 | 23 | resource "random_string" "sqs_rstring" { 24 | length = 18 25 | special = false 26 | upper = false 27 | } 28 | 29 | resource "aws_sqs_queue" "ec2_asg_test_sqs" { 30 | name = "${random_string.sqs_rstring.result}-my-example-queue" 31 | } 32 | 33 | module "sns" { 34 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-sns?ref=v0.12.2" 35 | 36 | create_subscription_1 = true 37 | endpoint_1 = aws_sqs_queue.ec2_asg_test_sqs.arn 38 | name = "${random_string.sqs_rstring.result}-ec2-asg-test-topic" 39 | protocol_1 = "sqs" 40 | } 41 | 42 | 43 | module "clb" { 44 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-clb?ref=v0.12.4" 45 | 46 | name = "${random_string.name_rstring.result}-ec2-asg-clb-example" 47 | security_groups = [module.vpc.default_sg] 48 | subnets = module.vpc.public_subnets 49 | internal_loadbalancer = false 50 | create_logging_bucket = false 51 | rackspace_managed = false 52 | 53 | tags = { 54 | Example = "Example-clb" 55 | } 56 | 57 | 58 | listeners = [ 59 | { 60 | instance_port = 8000 61 | instance_protocol = "HTTP" 62 | lb_port = 80 63 | lb_protocol = "HTTP" 64 | }, 65 | ] 66 | } 67 | 68 | module "ec2_asg" { 69 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-ec2_asg?ref=v0.12.23" 70 | 71 | asg_count = "2" 72 | asg_wait_for_capacity_timeout = "10m" 73 | backup_tag_value = "False" 74 | cloudwatch_log_retention = "30" 75 | cw_high_evaluations = "3" 76 | cw_high_operator = "GreaterThanThreshold" 77 | cw_high_period = "60" 78 | cw_high_threshold = "60" 79 | cw_low_evaluations = "3" 80 | cw_low_operator = "LessThanThreshold" 81 | cw_low_period = "300" 82 | cw_low_threshold = "30" 83 | cw_scaling_metric = "CPUUtilization" 84 | detailed_monitoring = true 85 | ec2_os = "centos7" 86 | ec2_scale_down_adjustment = "1" 87 | ec2_scale_down_cool_down = "60" 88 | ec2_scale_up_adjustment = "1" 89 | ec2_scale_up_cool_down = "60" 90 | enable_ebs_optimization = false 91 | enable_scaling_notification = true 92 | encrypt_secondary_ebs_volume = false 93 | environment = "Development" 94 | health_check_grace_period = "300" 95 | health_check_type = "EC2" 96 | install_codedeploy_agent = false 97 | instance_role_managed_policy_arn_count = "3" 98 | instance_type = "t2.micro" 99 | load_balancer_names = [module.clb.name] 100 | name = "${random_string.name_rstring.result}-ec2-asg-instance-example" 101 | perform_ssm_inventory_tag = "True" 102 | primary_ebs_volume_iops = "0" 103 | primary_ebs_volume_size = "60" 104 | primary_ebs_volume_type = "gp2" 105 | rackspace_managed = true 106 | scaling_max = "2" 107 | scaling_min = "1" 108 | scaling_notification_topic = module.sns.topic_arn 109 | secondary_ebs_volume_iops = "0" 110 | secondary_ebs_volume_size = "60" 111 | secondary_ebs_volume_type = "gp2" 112 | security_groups = [module.vpc.default_sg] 113 | ssm_association_refresh_rate = "rate(1 day)" 114 | ssm_patching_group = "MyPatchGroup1" 115 | subnets = [element(module.vpc.public_subnets, 0), element(module.vpc.public_subnets, 1)] 116 | tenancy = "default" 117 | terminated_instances = "30" 118 | 119 | 120 | instance_role_managed_policy_arns = [ 121 | "arn:aws:iam::aws:policy/AmazonEC2FullAccess", 122 | "arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetTaggingRole", 123 | "arn:aws:iam::aws:policy/CloudWatchActionsEC2Access", 124 | ] 125 | 126 | ssm_bootstrap_list = [ 127 | { 128 | action = "aws:runDocument", 129 | inputs = { 130 | documentPath = "arn:aws:ssm:${data.aws_region.current_region.name}:507897595701:document/Rack-Install_Package", 131 | documentParameters = { 132 | Packages = "tmux" 133 | }, 134 | documentType = "SSMDocument" 135 | }, 136 | name = "InstallTmux", 137 | timeoutSeconds = 300 138 | }, 139 | { 140 | action = "aws:runDocument", 141 | inputs = { 142 | documentPath = "AWS-RunShellScript", 143 | documentParameters = { 144 | commands = ["touch /tmp/myfile"] 145 | }, 146 | documentType = "SSMDocument" 147 | }, 148 | name = "CreateFile", 149 | timeoutSeconds = 300 150 | }, 151 | ] 152 | 153 | tags = { 154 | MyTag1 = "Myvalue1" 155 | MyTag2 = "Myvalue2" 156 | MyTag3 = "Myvalue3" 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /examples/custom_ami.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | } 4 | 5 | provider "aws" { 6 | version = "~> 3.0" 7 | region = "us-west-2" 8 | } 9 | 10 | resource "random_string" "name_rstring" { 11 | length = 8 12 | special = false 13 | } 14 | 15 | module "vpc" { 16 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-vpc_basenetwork?ref=v0.12.7" 17 | 18 | name = "${random_string.name_rstring.result}-ec2-asg-basenetwork-example" 19 | } 20 | 21 | module "alb" { 22 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-alb//?ref=v0.12.10" 23 | 24 | create_logging_bucket = false 25 | http_listeners_count = 1 26 | name = "${random_string.name_rstring.result}-test-alb" 27 | rackspace_managed = false 28 | security_groups = [module.vpc.default_sg] 29 | subnets = module.vpc.public_subnets 30 | target_groups_count = 1 31 | vpc_id = module.vpc.vpc_id 32 | 33 | http_listeners = [ 34 | { 35 | port = 80 36 | protocol = "HTTP" 37 | }, 38 | ] 39 | 40 | target_groups = [ 41 | { 42 | backend_port = 80 43 | backend_protocol = "HTTP" 44 | name = "ExampleTargetGroup" 45 | tagert_type = "alb" 46 | 47 | } 48 | ] 49 | } 50 | 51 | 52 | 53 | data "aws_region" "current_region" {} 54 | 55 | data "aws_ami" "centos7_marketplace" { 56 | owners = ["aws-marketplace"] 57 | most_recent = true 58 | 59 | filter { 60 | name = "product-code" 61 | values = ["cvugziknvmxgqna9noibqnnsy"] 62 | } 63 | } 64 | 65 | resource "random_string" "sqs_rstring" { 66 | length = 18 67 | special = false 68 | upper = false 69 | } 70 | 71 | resource "aws_sqs_queue" "ec2_asg_test_sqs" { 72 | name = "${random_string.sqs_rstring.result}-my-example-queue" 73 | } 74 | 75 | module "sns" { 76 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-sns?ref=v0.12.2" 77 | 78 | create_subscription_1 = true 79 | endpoint_1 = aws_sqs_queue.ec2_asg_test_sqs.arn 80 | name = "${random_string.sqs_rstring.result}-ec2-asg-test-topic" 81 | protocol_1 = "sqs" 82 | } 83 | 84 | module "ec2_asg" { 85 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-ec2_asg?ref=v0.12.23" 86 | 87 | asg_count = "2" 88 | asg_wait_for_capacity_timeout = "10m" 89 | backup_tag_value = "False" 90 | cloudwatch_log_retention = "30" 91 | cw_high_evaluations = "3" 92 | cw_high_operator = "GreaterThanThreshold" 93 | cw_high_period = "60" 94 | cw_high_threshold = "60" 95 | cw_low_evaluations = "3" 96 | cw_low_operator = "LessThanThreshold" 97 | cw_low_period = "300" 98 | cw_low_threshold = "30" 99 | cw_scaling_metric = "CPUUtilization" 100 | detailed_monitoring = true 101 | ec2_os = "centos7" 102 | ec2_scale_down_adjustment = "1" 103 | ec2_scale_down_cool_down = "60" 104 | ec2_scale_up_adjustment = "1" 105 | ec2_scale_up_cool_down = "60" 106 | enable_ebs_optimization = false 107 | enable_scaling_notification = true 108 | encrypt_secondary_ebs_volume = false 109 | environment = "Development" 110 | health_check_grace_period = "300" 111 | health_check_type = "EC2" 112 | image_id = data.aws_ami.centos7_marketplace.id 113 | install_codedeploy_agent = false 114 | instance_role_managed_policy_arn_count = "3" 115 | instance_type = "t2.micro" 116 | target_group_arns = module.alb.target_group_arns 117 | name = "${random_string.name_rstring.result}-ec2-asg-custom-ami-example" 118 | perform_ssm_inventory_tag = "True" 119 | primary_ebs_volume_iops = "0" 120 | primary_ebs_volume_size = "60" 121 | primary_ebs_volume_type = "gp2" 122 | rackspace_managed = true 123 | scaling_max = "2" 124 | scaling_min = "1" 125 | scaling_notification_topic = module.sns.topic_arn 126 | secondary_ebs_volume_iops = "0" 127 | secondary_ebs_volume_size = "60" 128 | secondary_ebs_volume_type = "gp2" 129 | security_groups = [module.vpc.default_sg] 130 | ssm_association_refresh_rate = "rate(1 day)" 131 | ssm_patching_group = "MyPatchGroup1" 132 | subnets = [element(module.vpc.public_subnets, 0), element(module.vpc.public_subnets, 1)] 133 | tenancy = "default" 134 | terminated_instances = "30" 135 | 136 | instance_role_managed_policy_arns = [ 137 | "arn:aws:iam::aws:policy/AmazonEC2FullAccess", 138 | "arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetTaggingRole", 139 | "arn:aws:iam::aws:policy/CloudWatchActionsEC2Access", 140 | ] 141 | 142 | 143 | ssm_bootstrap_list = [ 144 | { 145 | action = "aws:runDocument", 146 | inputs = { 147 | documentPath = "arn:aws:ssm:${data.aws_region.current_region.name}:507897595701:document/Rack-Install_Package", 148 | documentParameters = { 149 | Packages = "tmux" 150 | }, 151 | documentType = "SSMDocument" 152 | }, 153 | name = "InstallTmux", 154 | timeoutSeconds = 300 155 | }, 156 | { 157 | action = "aws:runDocument", 158 | inputs = { 159 | documentPath = "AWS-RunShellScript", 160 | documentParameters = { 161 | commands = ["touch /tmp/myfile"] 162 | }, 163 | documentType = "SSMDocument" 164 | }, 165 | name = "CreateFile", 166 | timeoutSeconds = 300 167 | }, 168 | ] 169 | 170 | tags = { 171 | MyTag1 = "Myvalue1" 172 | MyTag2 = "Myvalue2" 173 | MyTag3 = "Myvalue3" 174 | } 175 | } 176 | 177 | -------------------------------------------------------------------------------- /examples/custom_cw_config.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | cwagent_vars = { 3 | application_log_group_name = "custom_app_log_group_name" 4 | system_log_group_name = "custom_system_log_group_name" 5 | } 6 | } 7 | 8 | terraform { 9 | required_version = ">= 1.0.0" 10 | } 11 | 12 | provider "aws" { 13 | version = "~> 3.0" 14 | region = "us-west-2" 15 | } 16 | 17 | resource "random_string" "name_rstring" { 18 | length = 8 19 | special = false 20 | } 21 | 22 | 23 | module "vpc" { 24 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-vpc_basenetwork?ref=v0.12.7" 25 | 26 | name = "${random_string.name_rstring.result}-ec2-asg-basenetwork-example" 27 | } 28 | 29 | data "aws_region" "current_region" {} 30 | 31 | resource "random_string" "sqs_rstring" { 32 | length = 18 33 | special = false 34 | upper = false 35 | } 36 | 37 | resource "aws_sqs_queue" "ec2_asg_test_sqs" { 38 | name = "${random_string.sqs_rstring.result}-my-example-queue" 39 | } 40 | 41 | module "sns" { 42 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-sns?ref=v0.12.2" 43 | 44 | create_subscription_1 = true 45 | endpoint_1 = aws_sqs_queue.ec2_asg_test_sqs.arn 46 | name = "${random_string.sqs_rstring.result}-ec2-asg-test-topic" 47 | protocol_1 = "sqs" 48 | } 49 | 50 | 51 | module "clb" { 52 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-clb?ref=v0.12.4" 53 | 54 | name = "${random_string.name_rstring.result}-ec2-asg-clb-example" 55 | security_groups = [module.vpc.default_sg] 56 | subnets = module.vpc.public_subnets 57 | internal_loadbalancer = false 58 | create_logging_bucket = false 59 | rackspace_managed = false 60 | 61 | tags = { 62 | Example = "Example-clb" 63 | } 64 | 65 | 66 | listeners = [ 67 | { 68 | instance_port = 8000 69 | instance_protocol = "HTTP" 70 | lb_port = 80 71 | lb_protocol = "HTTP" 72 | }, 73 | ] 74 | } 75 | 76 | module "ec2_asg" { 77 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-ec2_asg?ref=v0.12.23" 78 | 79 | asg_count = "2" 80 | asg_wait_for_capacity_timeout = "10m" 81 | backup_tag_value = "False" 82 | cloudwatch_log_retention = "30" 83 | custom_cw_agent_config_ssm_param = aws_ssm_parameter.custom_cwagentparam.name 84 | cw_high_evaluations = "3" 85 | cw_high_operator = "GreaterThanThreshold" 86 | cw_high_period = "60" 87 | cw_high_threshold = "60" 88 | cw_low_evaluations = "3" 89 | cw_low_operator = "LessThanThreshold" 90 | cw_low_period = "300" 91 | cw_low_threshold = "30" 92 | cw_scaling_metric = "CPUUtilization" 93 | detailed_monitoring = true 94 | ec2_os = "centos7" 95 | ec2_scale_down_adjustment = "1" 96 | ec2_scale_down_cool_down = "60" 97 | ec2_scale_up_adjustment = "1" 98 | ec2_scale_up_cool_down = "60" 99 | enable_ebs_optimization = false 100 | enable_scaling_notification = true 101 | encrypt_secondary_ebs_volume = false 102 | environment = "Development" 103 | health_check_grace_period = "300" 104 | health_check_type = "EC2" 105 | install_codedeploy_agent = false 106 | instance_role_managed_policy_arn_count = "2" 107 | instance_type = "t2.micro" 108 | load_balancer_names = [module.clb.name] 109 | name = "${random_string.name_rstring.result}-ec2-asg-instance-example" 110 | perform_ssm_inventory_tag = "True" 111 | primary_ebs_volume_iops = "0" 112 | primary_ebs_volume_size = "60" 113 | primary_ebs_volume_type = "gp2" 114 | provide_custom_cw_agent_config = true 115 | rackspace_managed = true 116 | scaling_max = "2" 117 | scaling_min = "1" 118 | scaling_notification_topic = module.sns.topic_arn 119 | secondary_ebs_volume_iops = "0" 120 | secondary_ebs_volume_size = "60" 121 | secondary_ebs_volume_type = "gp2" 122 | security_groups = [module.vpc.default_sg] 123 | ssm_association_refresh_rate = "rate(1 day)" 124 | ssm_patching_group = "MyPatchGroup1" 125 | subnets = [element(module.vpc.public_subnets, 0), element(module.vpc.public_subnets, 1)] 126 | tenancy = "default" 127 | terminated_instances = "30" 128 | 129 | instance_role_managed_policy_arns = [ 130 | "arn:aws:iam::aws:policy/AmazonEC2FullAccess", 131 | "arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetTaggingRole", 132 | "arn:aws:iam::aws:policy/CloudWatchActionsEC2Access", 133 | ] 134 | 135 | ssm_bootstrap_list = [ 136 | { 137 | action = "aws:runDocument", 138 | inputs = { 139 | documentPath = "arn:aws:ssm:${data.aws_region.current_region.name}:507897595701:document/Rack-Install_Package", 140 | documentParameters = { 141 | Packages = "tmux" 142 | }, 143 | documentType = "SSMDocument" 144 | }, 145 | name = "InstallTmux", 146 | timeoutSeconds = 300 147 | }, 148 | { 149 | action = "aws:runDocument", 150 | inputs = { 151 | documentPath = "AWS-RunShellScript", 152 | documentParameters = { 153 | commands = ["touch /tmp/myfile"] 154 | }, 155 | documentType = "SSMDocument" 156 | }, 157 | name = "CreateFile", 158 | timeoutSeconds = 300 159 | }, 160 | ] 161 | 162 | tags = { 163 | MyTag1 = "Myvalue1" 164 | MyTag2 = "Myvalue2" 165 | MyTag3 = "Myvalue3" 166 | } 167 | } 168 | 169 | resource "random_string" "res_name" { 170 | length = 8 171 | lower = true 172 | number = false 173 | special = false 174 | upper = false 175 | } 176 | 177 | resource "aws_ssm_parameter" "custom_cwagentparam" { 178 | description = "Custom Cloudwatch Agent configuration" 179 | name = "custom_cw_param-${random_string.res_name.result}" 180 | type = "String" 181 | value = templatefile("./text/linux_cw_agent_param.json", local.cwagent_vars) 182 | } -------------------------------------------------------------------------------- /examples/text/linux_cw_agent_param.json: -------------------------------------------------------------------------------- 1 | {"metrics":{"append_dimensions":{"InstanceId":"$${aws:InstanceId}","AutoScalingGroupName":"$${aws:AutoScalingGroupName}"},"aggregation_dimensions":[["InstanceId"],["AutoScalingGroupName"],["InstanceId","device"]],"namespace":"System/Linux","metrics_collected":{"mem":{"metrics_collection_interval":60,"measurement":[{"rename":"MemoryUtilization","name":"mem_used_percent","unit":"Percent"}]},"disk":{"ignore_file_system_types":["devtmpfs","tmpfs","devfs","rootfs"],"metrics_collection_interval":60,"resources":["*"],"measurement":["used_percent"]}}},"logs":{"logs_collected":{"files":{"collect_list":[{"file_path":"/var/log/cloud-init-output.log","log_group_name":"${system_log_group_name}","log_stream_name":"{instance_id}/cloud-init-output.log"},{"timestamp_format":"%b %d %H:%M:%S","file_path":"/var/log/cloud-init.log","log_group_name":"${system_log_group_name}","log_stream_name":"{instance_id}/cloud-init.log"},{"timestamp_format":"%Y-%m-%d %H:%M:%S","multi_line_start_pattern":"{timestamp_format}","file_path":"/var/log/amazon/ssm/amazon-ssm-agent.log","log_group_name":"${system_log_group_name}","log_stream_name":"{instance_id}/amazon-ssm-agent.log"},{"timestamp_format":"%Y-%m-%d %H:%M:%S","multi_line_start_pattern":"{timestamp_format}","file_path":"/var/log/amazon/ssm/errors.log","log_group_name":"${system_log_group_name}","log_stream_name":"{instance_id}/amazon-ssm-errors.log"},{"timestamp_format":"%d/%b/%Y:%H:%M:%S","file_path":"/var/log/httpd/access*","log_group_name":"${application_log_group_name}","log_stream_name":"{instance_id}/httpd-access"},{"timestamp_format":"%d/%b/%Y:%H:%M:%S","file_path":"/var/log/httpd/error*","log_group_name":"${application_log_group_name}","log_stream_name":"{instance_id}/httpd-error"},{"timestamp_format":"%d/%b/%Y:%H:%M:%S","file_path":"/var/log/apache2/access*","log_group_name":"${application_log_group_name}","log_stream_name":"{instance_id}/apache2-access"},{"timestamp_format":"%d/%b/%Y:%H:%M:%S","file_path":"/var/log/apache2/error*","log_group_name":"${application_log_group_name}","log_stream_name":"{instance_id}/apache2-error"},{"timestamp_format":"%d/%b/%Y:%H:%M:%S","file_path":"/var/log/nginx/access*","log_group_name":"${application_log_group_name}","log_stream_name":"{instance_id}/nginx-access"},{"timestamp_format":"%d/%b/%Y:%H:%M:%S","file_path":"/var/log/nginx/error*","log_group_name":"${application_log_group_name}","log_stream_name":"{instance_id}/nginx-error"},{"timestamp_format":"%a %b %d %H:%M:%S","file_path":"/etc/openvpn/openvpn.log*","log_group_name":"${application_log_group_name}","log_stream_name":"{instance_id}/openvpn.log"}]}}}} -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * # aws-terraform-ec2_asg 3 | * 4 | * This module creates one or more autoscaling groups. 5 | * 6 | * ## Basic Usage 7 | * 8 | * ```HCL 9 | * module "asg" { 10 | * source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-ec2_asg//?ref=v0.12.16" 11 | * 12 | * ec2_os = "amazon2" 13 | * name = "my_asg" 14 | * security_groups = [module.sg.private_web_security_group_id] 15 | * subnets = module.vpc.private_subnets 16 | * } 17 | * ``` 18 | * 19 | * Full working references are available at [examples](examples) 20 | * 21 | * ## Other TF Modules Used 22 | * 23 | * Using [aws-terraform-cloudwatch_alarm](https://github.com/rackspace-infrastructure-automation/aws-terraform-cloudwatch_alarm) to create the following CloudWatch Alarms: 24 | * - group_terminating_instances 25 | * 26 | * ## Terraform 0.12 upgrade 27 | * 28 | * Several changes were required while adding terraform 0.12 compatibility. The following changes should 29 | * made when upgrading from a previous release to version 0.12.0 or higher. 30 | * 31 | * ### Module variables 32 | * 33 | * The following module variables were updated to better meet current Rackspace style guides: 34 | * 35 | * - `security_group_list` -> `security_groups` 36 | * - `resource_name` -> `name` 37 | * 38 | * The following variables are no longer neccessary and were removed 39 | * 40 | * - `additional_ssm_bootstrap_step_count` 41 | * - `install_scaleft_agent` 42 | * 43 | * Several new variables were introduced to provide existing functionality, with a simplified format. The original formmating was also retained to allow easier transition. 44 | * 45 | * New variables `tags` and `tags_asg` were added to replace the functionality of the `additional_tags` variable. `tags` allows setting tags on all resources, while `tags_asg` sets tags only on the ASG itself. `additional_tags` will continue to work as expected, but will be removed in a future release. 46 | * 47 | * New variable `ssm_bootstrap_list` was added to allow setting the SSM association steps using objects instead of strings, allowing easier linting and formatting of these lines. The `additional_ssm_bootstrap_list` variable will continue to work, but will be deprecated in a future release. 48 | */ 49 | 50 | locals { 51 | user_data_vars = { 52 | initial_commands = var.initial_userdata_commands 53 | final_commands = var.final_userdata_commands 54 | } 55 | } 56 | 57 | terraform { 58 | required_version = ">= 1.0.0" 59 | 60 | required_providers { 61 | aws = "~> 3.0" 62 | } 63 | } 64 | 65 | locals { 66 | ec2_os = lower(var.ec2_os) 67 | 68 | ec2_os_windows_length_test = length(local.ec2_os) >= 7 ? 7 : length(local.ec2_os) 69 | ec2_os_windows = substr(local.ec2_os, 0, local.ec2_os_windows_length_test) == "windows" ? true : false 70 | 71 | # Enforce metrics needed for CW 72 | asg_metrics = distinct(concat(var.enabled_asg_metrics, ["GroupTerminatingInstances"])) 73 | 74 | cw_config_parameter_name = "CWAgent-${var.name}" 75 | 76 | ssm_doc_content = { 77 | schemaVersion = "2.2" 78 | description = "SSM Document for instance configuration." 79 | parameters = {} 80 | mainSteps = local.ssm_command_list 81 | } 82 | 83 | ssm_command_list = concat( 84 | local.default_ssm_cmd_list, 85 | local.ssm_codedeploy_include[var.install_codedeploy_agent], 86 | [for s in var.additional_ssm_bootstrap_list : jsondecode(s.ssm_add_step)], 87 | var.ssm_bootstrap_list, 88 | ) 89 | 90 | # This is a list of ssm main steps 91 | default_ssm_cmd_list = [ 92 | { 93 | action = "aws:runDocument" 94 | name = "BusyWait" 95 | timeoutSeconds = 300 96 | 97 | inputs = { 98 | documentPath = "AWS-RunDocument" 99 | documentType = "SSMDocument" 100 | 101 | documentParameters = { 102 | documentParameters = {} 103 | sourceInfo = "{\"path\": \"https://rackspace-ssm-docs-${data.aws_region.current_region.name}.s3.amazonaws.com/latest/configuration/Rack-BusyWait.json\"}" 104 | sourceType = "S3" 105 | } 106 | } 107 | }, 108 | { 109 | action = "aws:runDocument" 110 | name = "InstallCWAgent" 111 | timeoutSeconds = 300 112 | 113 | inputs = { 114 | documentPath = "AWS-ConfigureAWSPackage" 115 | documentType = "SSMDocument" 116 | 117 | documentParameters = { 118 | action = "Install" 119 | name = "AmazonCloudWatchAgent" 120 | } 121 | } 122 | }, 123 | { 124 | action = "aws:runDocument" 125 | name = "ConfigureCWAgent" 126 | timeoutSeconds = 300 127 | 128 | inputs = { 129 | documentPath = "AmazonCloudWatch-ManageAgent" 130 | documentType = "SSMDocument" 131 | 132 | documentParameters = { 133 | action = "configure" 134 | name = "AmazonCloudWatchAgent" 135 | optionalConfigurationLocation = var.provide_custom_cw_agent_config ? var.custom_cw_agent_config_ssm_param : local.cw_config_parameter_name 136 | optionalConfigurationSource = "ssm" 137 | optionalRestart = "yes" 138 | } 139 | } 140 | }, 141 | { 142 | action = "aws:runDocument" 143 | name = "SetupTimeSync" 144 | timeoutSeconds = 300 145 | 146 | inputs = { 147 | documentPath = "AWS-RunDocument" 148 | documentType = "SSMDocument" 149 | 150 | documentParameters = { 151 | documentParameters = {} 152 | sourceInfo = "{\"path\": \"https://rackspace-ssm-docs-${data.aws_region.current_region.name}.s3.amazonaws.com/latest/configuration/Rack-ConfigureAWSTimeSync.json\"}" 153 | sourceType = "S3" 154 | } 155 | } 156 | }, 157 | { 158 | action = "aws:runDocument" 159 | name = "DiagnosticTools" 160 | timeoutSeconds = 300 161 | 162 | inputs = { 163 | documentPath = "AWS-RunDocument" 164 | documentType = "SSMDocument" 165 | 166 | documentParameters = { 167 | documentParameters = { Packages = lookup(local.diagnostic_packages, local.ec2_os, "") } 168 | sourceInfo = "{\"path\": \"https://rackspace-ssm-docs-${data.aws_region.current_region.name}.s3.amazonaws.com/latest/configuration/Rack-Install_Package.json\"}" 169 | sourceType = "S3" 170 | } 171 | } 172 | }, 173 | { 174 | action = "aws:runDocument" 175 | name = "SetMotd" 176 | timeoutSeconds = 300 177 | 178 | inputs = { 179 | documentPath = "AWS-RunDocument" 180 | documentType = "SSMDocument" 181 | 182 | documentParameters = { 183 | documentParameters = {} 184 | sourceInfo = "{\"path\": \"https://rackspace-ssm-docs-${data.aws_region.current_region.name}.s3.amazonaws.com/latest/configuration/Rack-SetMotd.json\"}" 185 | sourceType = "S3" 186 | } 187 | } 188 | }, 189 | ] 190 | 191 | ssm_codedeploy_include = { 192 | true = [ 193 | { 194 | action = "aws:runDocument" 195 | name = "InstallCodeDeployAgent" 196 | timeoutSeconds = 300 197 | 198 | inputs = { 199 | documentPath = "AWS-RunDocument" 200 | documentType = "SSMDocument" 201 | 202 | documentParameters = { 203 | documentParameters = {} 204 | sourceInfo = "{\"path\": \"https://rackspace-ssm-docs-${data.aws_region.current_region.name}.s3.amazonaws.com/latest/configuration/Rack-Install_CodeDeploy.json\"}" 205 | sourceType = "S3" 206 | } 207 | } 208 | }, 209 | ] 210 | 211 | false = [] 212 | } 213 | 214 | defaults = { 215 | diagnostic_packages = { 216 | amazon = "sysstat ltrace strace iptraf tcpdump" 217 | rhel = "sysstat ltrace strace lsof iotop iptraf-ng tcpdump" 218 | ubuntu = "sysstat iotop iptraf-ng" 219 | debian = "sysstat iotop iptraf-ng" 220 | } 221 | } 222 | 223 | diagnostic_packages = { 224 | amazon2 = local.defaults["diagnostic_packages"]["amazon"] 225 | amazon2023 = local.defaults["diagnostic_packages"]["amazon"] 226 | amazoneks = local.defaults["diagnostic_packages"]["amazon"] 227 | amazonecs = local.defaults["diagnostic_packages"]["amazon"] 228 | rhel7 = local.defaults["diagnostic_packages"]["rhel"] 229 | rhel8 = local.defaults["diagnostic_packages"]["rhel"] 230 | centos7 = local.defaults["diagnostic_packages"]["rhel"] 231 | ubuntu18 = local.defaults["diagnostic_packages"]["ubuntu"] 232 | ubuntu20 = local.defaults["diagnostic_packages"]["ubuntu"] 233 | debian10 = local.defaults["diagnostic_packages"]["debian"] 234 | debian11 = local.defaults["diagnostic_packages"]["debian"] 235 | } 236 | 237 | ebs_device_map = { 238 | amazon2 = "/dev/sdf" 239 | amazon2023 = "/dev/sdf" 240 | amazoneks = "/dev/sdf" 241 | amazonecs = "/dev/xvdcz" 242 | rhel7 = "/dev/sdf" 243 | rhel8 = "/dev/sdf" 244 | centos7 = "/dev/sdf" 245 | ubuntu18 = "/dev/sdf" 246 | ubuntu20 = "/dev/sdf" 247 | debian10 = "/dev/sdf" 248 | debian11 = "/dev/sdf" 249 | windows2016 = "xvdf" 250 | windows2019 = "xvdf" 251 | windows2022 = "xvdf" 252 | } 253 | 254 | root_device_map = { 255 | amazon2 = "/dev/xvda" 256 | amazon2023 = "/dev/xvda" 257 | amazoneks = "/dev/xvda" 258 | amazonecs = "/dev/xvda" 259 | rhel7 = "/dev/sda1" 260 | rhel8 = "/dev/sda1" 261 | centos7 = "/dev/sda1" 262 | ubuntu18 = "/dev/sda1" 263 | ubuntu20 = "/dev/sda1" 264 | windows2016 = "/dev/sda1" 265 | windows2019 = "/dev/sda1" 266 | windows2022 = "/dev/sda1" 267 | debian10 = "/dev/sda1" 268 | debian11 = "/dev/sda1" 269 | } 270 | 271 | cwagent_config = local.ec2_os_windows ? "windows_cw_agent_param.json" : "linux_cw_agent_param.json" 272 | 273 | # local.tags can and should be applied to all taggable resources 274 | 275 | tags = { 276 | Environment = var.environment 277 | ServiceProvider = "Rackspace" 278 | } 279 | 280 | # local.tags_ec2 is applied to the ASG and propagated to all instances 281 | 282 | tags_ec2 = { 283 | Backup = var.backup_tag_value 284 | Name = var.name 285 | "Patch Group" = var.ssm_patching_group 286 | SSMInventory = var.perform_ssm_inventory_tag 287 | "SSM Target Tag" = "Target-${var.name}" 288 | } 289 | 290 | # local.tags_asg is applied to the ASG but not propagated to the EC2 instances 291 | 292 | tags_asg = { 293 | InstanceReplacement = var.enable_rolling_updates ? "True" : "False" 294 | } 295 | 296 | user_data_map = { 297 | amazon2 = "amazon_linux_userdata.sh" 298 | amazon2023 = "amazon_linux_userdata.sh" 299 | amazonecs = "amazon_linux_userdata.sh" 300 | amazoneks = "amazon_linux_userdata.sh" 301 | rhel7 = "rhel_centos_7_userdata.sh" 302 | rhel8 = "rhel_centos_8_userdata.sh" 303 | centos7 = "rhel_centos_7_userdata.sh" 304 | ubuntu18 = "ubuntu_userdata.sh" 305 | ubuntu20 = "ubuntu_userdata.sh" 306 | debian10 = "debian_userdata.sh" 307 | debian11 = "debian_userdata.sh" 308 | windows2016 = "windows_userdata.ps1" 309 | windows2019 = "windows_userdata.ps1" 310 | windows2022 = "windows_userdata.ps1" 311 | } 312 | 313 | ami_owner_mapping = { 314 | amazon2 = "137112412989" 315 | amazon2023 = "137112412989" 316 | amazonecs = "591542846629" 317 | amazoneks = "602401143452" 318 | centos7 = "125523088429" 319 | rhel7 = "309956199498" 320 | rhel8 = "309956199498" 321 | ubuntu18 = "099720109477" 322 | ubuntu20 = "099720109477" 323 | debian10 = "136693071363" 324 | debian11 = "136693071363" 325 | windows2016 = "801119661308" 326 | windows2019 = "801119661308" 327 | windows2022 = "801119661308" 328 | } 329 | 330 | ami_name_mapping = { 331 | amazon2 = "amzn2-ami-hvm-2.0.*-ebs" 332 | amazon2023 = "al2023-ami-2023*-kernel-*-x86_64" 333 | amazonecs = "amzn2-ami-ecs-hvm-2*-x86_64-ebs" 334 | amazoneks = "amazon-eks-node-*" 335 | centos7 = "CentOS Linux 7 x86_64*" 336 | rhel7 = "RHEL-7.*_HVM-*x86_64*" 337 | rhel8 = "RHEL-8.*_HVM-*x86_64*" 338 | debian10 = "debian-10-amd64-*" 339 | debian11 = "debian-11-amd64-*" 340 | ubuntu18 = "ubuntu/images/hvm-ssd/*ubuntu-bionic-18.04-amd64-server*" 341 | ubuntu20 = "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*" 342 | windows2016 = "Windows_Server-2016-English-Full-Base*" 343 | windows2019 = "Windows_Server-2019-English-Full-Base*" 344 | windows2022 = "Windows_Server-2022-English-Full-Base*" 345 | } 346 | 347 | # Any custom AMI filters for a given OS can be added in this mapping 348 | image_filter = { 349 | amazon2 = [] 350 | amazon2023 = [] 351 | amazonecs = [] 352 | amazoneks = [] 353 | centos7 = [] 354 | rhel7 = [] 355 | rhel8 = [] 356 | ubuntu18 = [] 357 | ubuntu20 = [] 358 | debian10 = [] 359 | debian11 = [] 360 | windows2016 = [] 361 | windows2019 = [] 362 | windows2022 = [] 363 | } 364 | 365 | standard_filters = [ 366 | { 367 | name = "virtualization-type" 368 | values = ["hvm"] 369 | }, 370 | { 371 | name = "root-device-type" 372 | values = ["ebs"] 373 | }, 374 | { 375 | name = "name" 376 | values = [local.ami_name_mapping[local.ec2_os]] 377 | }, 378 | ] 379 | } 380 | 381 | # Lookup the correct AMI based on the region specified 382 | data "aws_ami" "asg_ami" { 383 | most_recent = true 384 | owners = [local.ami_owner_mapping[local.ec2_os]] 385 | 386 | dynamic "filter" { 387 | for_each = concat(local.standard_filters, local.image_filter[local.ec2_os]) 388 | content { 389 | name = filter.value.name 390 | values = filter.value.values 391 | } 392 | } 393 | } 394 | 395 | data "aws_region" "current_region" {} 396 | 397 | data "aws_caller_identity" "current_account" {} 398 | 399 | # 400 | # IAM policies 401 | # 402 | 403 | data "aws_iam_policy_document" "mod_ec2_assume_role_policy_doc" { 404 | statement { 405 | actions = ["sts:AssumeRole"] 406 | effect = "Allow" 407 | 408 | principals { 409 | identifiers = ["ec2.amazonaws.com"] 410 | type = "Service" 411 | } 412 | } 413 | } 414 | 415 | data "aws_iam_policy_document" "mod_ec2_instance_role_policies" { 416 | 417 | statement { 418 | effect = "Allow" 419 | resources = ["*"] 420 | 421 | actions = [ 422 | "ssm:CreateAssociation", 423 | "ssm:DescribeInstanceInformation", 424 | "ssm:GetParameter", 425 | ] 426 | } 427 | 428 | statement { 429 | effect = "Allow" 430 | resources = ["*"] 431 | 432 | actions = [ 433 | "cloudwatch:GetMetricStatistics", 434 | "cloudwatch:ListMetrics", 435 | "cloudwatch:PutMetricData", 436 | "ec2:DescribeTags", 437 | "logs:CreateLogGroup", 438 | "logs:CreateLogStream", 439 | "logs:DescribeLogStreams", 440 | "logs:PutLogEvents", 441 | ] 442 | } 443 | 444 | statement { 445 | effect = "Allow" 446 | resources = ["arn:aws:s3:::rackspace-*/*"] 447 | 448 | actions = [ 449 | "s3:AbortMultipartUpload", 450 | "s3:GetBucketLocation", 451 | "s3:GetEncryptionConfiguration", 452 | "s3:GetObject", 453 | "s3:ListBucket", 454 | "s3:ListBucketMultipartUploads", 455 | "s3:ListMultipartUploadParts", 456 | "s3:PutObject", 457 | ] 458 | } 459 | } 460 | 461 | resource "aws_iam_policy" "create_instance_role_policy" { 462 | count = var.instance_profile_override ? 0 : 1 463 | 464 | description = "Rackspace Instance Role Policies for EC2" 465 | name = "InstanceRolePolicy-${var.name}" 466 | policy = data.aws_iam_policy_document.mod_ec2_instance_role_policies.json 467 | } 468 | 469 | resource "aws_iam_role" "mod_ec2_instance_role" { 470 | count = var.instance_profile_override ? 0 : 1 471 | 472 | assume_role_policy = data.aws_iam_policy_document.mod_ec2_assume_role_policy_doc.json 473 | name = "InstanceRole-${var.name}" 474 | path = "/" 475 | } 476 | 477 | resource "aws_iam_role_policy_attachment" "attach_core_ssm_policy" { 478 | count = var.instance_profile_override ? 0 : 1 479 | 480 | policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" 481 | role = aws_iam_role.mod_ec2_instance_role[0].name 482 | } 483 | 484 | resource "aws_iam_role_policy_attachment" "attach_cw_ssm_policy" { 485 | count = var.instance_profile_override ? 0 : 1 486 | 487 | policy_arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy" 488 | role = aws_iam_role.mod_ec2_instance_role[0].name 489 | } 490 | 491 | resource "aws_iam_role_policy_attachment" "attach_ad_ssm_policy" { 492 | count = var.instance_profile_override ? 0 : 1 493 | 494 | policy_arn = "arn:aws:iam::aws:policy/AmazonSSMDirectoryServiceAccess" 495 | role = aws_iam_role.mod_ec2_instance_role[0].name 496 | } 497 | 498 | resource "aws_iam_role_policy_attachment" "attach_codedeploy_policy" { 499 | count = var.install_codedeploy_agent && var.instance_profile_override != true ? 1 : 0 500 | 501 | policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforAWSCodeDeploy" 502 | role = aws_iam_role.mod_ec2_instance_role[0].name 503 | } 504 | 505 | resource "aws_iam_role_policy_attachment" "attach_instance_role_policy" { 506 | count = var.instance_profile_override ? 0 : 1 507 | 508 | policy_arn = aws_iam_policy.create_instance_role_policy[0].arn 509 | role = aws_iam_role.mod_ec2_instance_role[0].name 510 | } 511 | 512 | resource "aws_iam_role_policy_attachment" "attach_additonal_policies" { 513 | count = var.instance_profile_override ? 0 : var.instance_role_managed_policy_arn_count 514 | 515 | policy_arn = element(var.instance_role_managed_policy_arns, count.index) 516 | role = aws_iam_role.mod_ec2_instance_role[0].name 517 | } 518 | 519 | resource "aws_iam_instance_profile" "instance_role_instance_profile" { 520 | count = var.instance_profile_override ? 0 : 1 521 | 522 | name = "InstanceRoleInstanceProfile-${var.name}" 523 | path = "/" 524 | role = aws_iam_role.mod_ec2_instance_role[0].name 525 | } 526 | 527 | # 528 | # Provisioning of ASG related resources 529 | # 530 | 531 | resource "aws_launch_template" "launch_template_with_secondary_ebs" { 532 | count = var.secondary_ebs_volume_size != "" ? 1 : 0 533 | 534 | ebs_optimized = var.enable_ebs_optimization 535 | image_id = var.image_id != "" ? var.image_id : data.aws_ami.asg_ami.image_id 536 | instance_type = var.instance_type 537 | key_name = var.key_pair 538 | name_prefix = join("-", compact(["LaunchConfigWith2ndEbs", var.name, format("%03d-", count.index + 1)])) 539 | vpc_security_group_ids = var.security_groups 540 | user_data = base64encode(templatefile("${path.module}/text/${local.user_data_map[local.ec2_os]}", local.user_data_vars)) 541 | 542 | # Root block device 543 | block_device_mappings { 544 | device_name = local.root_device_map[local.ec2_os] 545 | ebs { 546 | iops = var.primary_ebs_volume_type == "io1" ? var.primary_ebs_volume_size : 0 547 | volume_size = var.primary_ebs_volume_size 548 | volume_type = var.primary_ebs_volume_type 549 | encrypted = var.encrypt_primary_ebs_volume 550 | } 551 | } 552 | block_device_mappings { 553 | device_name = local.ebs_device_map[local.ec2_os] 554 | ebs { 555 | encrypted = var.secondary_ebs_volume_existing_id == "" ? var.encrypt_secondary_ebs_volume : false 556 | iops = var.secondary_ebs_volume_iops 557 | snapshot_id = var.secondary_ebs_volume_existing_id 558 | volume_size = var.secondary_ebs_volume_size 559 | volume_type = var.secondary_ebs_volume_type 560 | } 561 | } 562 | iam_instance_profile { 563 | name = element( 564 | coalescelist(aws_iam_instance_profile.instance_role_instance_profile.*.name, 565 | [var.instance_profile_override_name], 566 | ), 567 | 0, 568 | ) 569 | } 570 | lifecycle { 571 | create_before_destroy = true 572 | } 573 | monitoring { 574 | enabled = var.detailed_monitoring 575 | } 576 | placement { 577 | tenancy = var.tenancy 578 | } 579 | metadata_options { 580 | http_endpoint = var.metadata_http_endpoint 581 | http_put_response_hop_limit = var.metadata_http_put_response_hop_limit 582 | http_tokens = var.metadata_http_tokens 583 | instance_metadata_tags = var.metadata_instance_metadata_tags 584 | } 585 | } 586 | 587 | 588 | resource "aws_launch_template" "launch_template_with_no_secondary_ebs" { 589 | count = var.secondary_ebs_volume_size != "" ? 0 : 1 590 | 591 | ebs_optimized = var.enable_ebs_optimization 592 | image_id = var.image_id != "" ? var.image_id : data.aws_ami.asg_ami.image_id 593 | instance_type = var.instance_type 594 | key_name = var.key_pair 595 | name_prefix = join("-", compact(["LaunchConfigWith2ndEbs", var.name, format("%03d-", count.index + 1)])) 596 | vpc_security_group_ids = var.security_groups 597 | user_data = base64encode(templatefile("${path.module}/text/${local.user_data_map[local.ec2_os]}", local.user_data_vars)) 598 | 599 | # Root block device 600 | block_device_mappings { 601 | device_name = local.root_device_map[local.ec2_os] 602 | ebs { 603 | iops = var.primary_ebs_volume_type == "io1" ? var.primary_ebs_volume_size : 0 604 | volume_size = var.primary_ebs_volume_size 605 | volume_type = var.primary_ebs_volume_type 606 | encrypted = var.encrypt_primary_ebs_volume 607 | } 608 | } 609 | iam_instance_profile { 610 | name = element( 611 | coalescelist(aws_iam_instance_profile.instance_role_instance_profile.*.name, 612 | [var.instance_profile_override_name], 613 | ), 614 | 0, 615 | ) 616 | } 617 | lifecycle { 618 | create_before_destroy = true 619 | } 620 | monitoring { 621 | enabled = var.detailed_monitoring 622 | } 623 | placement { 624 | tenancy = var.tenancy 625 | } 626 | metadata_options { 627 | http_endpoint = var.metadata_http_endpoint 628 | http_put_response_hop_limit = var.metadata_http_put_response_hop_limit 629 | http_tokens = var.metadata_http_tokens 630 | instance_metadata_tags = var.metadata_instance_metadata_tags 631 | } 632 | } 633 | 634 | resource "aws_autoscaling_policy" "ec2_scale_up_policy" { 635 | count = var.policy_type == "SimpleScaling" && var.enable_scaling_actions == true ? var.asg_count : 0 636 | 637 | adjustment_type = "ChangeInCapacity" 638 | autoscaling_group_name = element(aws_autoscaling_group.autoscalegrp.*.name, count.index) 639 | cooldown = var.ec2_scale_up_cool_down 640 | name = join("-", compact(["ec2_scale_up_policy", var.name, format("%03d", count.index + 1)])) 641 | scaling_adjustment = var.ec2_scale_up_adjustment 642 | } 643 | 644 | resource "aws_autoscaling_policy" "ec2_scale_down_policy" { 645 | count = var.policy_type == "SimpleScaling" && var.enable_scaling_actions == true ? var.asg_count : 0 646 | 647 | adjustment_type = "ChangeInCapacity" 648 | autoscaling_group_name = element(aws_autoscaling_group.autoscalegrp.*.name, count.index) 649 | cooldown = var.ec2_scale_down_cool_down 650 | name = join("-", compact(["ec2_scale_down_policy", var.name, format("%03d", count.index + 1)])) 651 | scaling_adjustment = var.ec2_scale_down_adjustment > 0 ? -var.ec2_scale_down_adjustment : var.ec2_scale_down_adjustment 652 | } 653 | 654 | resource "aws_autoscaling_policy" "ec2_scale_up_down_target_tracking" { 655 | count = var.policy_type == "TargetTrackingScaling" ? var.asg_count : 0 656 | 657 | name = join("-", compact(["ec2_scale_up_down_target_tracking_policy", var.name, format("%03d", count.index + 1)])) 658 | autoscaling_group_name = element(aws_autoscaling_group.autoscalegrp.*.name, count.index) 659 | estimated_instance_warmup = var.instance_warm_up_time 660 | policy_type = var.policy_type 661 | target_tracking_configuration { 662 | predefined_metric_specification { 663 | predefined_metric_type = var.tracking_policy_metric 664 | resource_label = var.alb_resource_label 665 | } 666 | target_value = var.target_value 667 | disable_scale_in = var.disable_scale_in 668 | } 669 | } 670 | 671 | resource "aws_autoscaling_group" "autoscalegrp" { 672 | count = var.asg_count 673 | 674 | enabled_metrics = local.asg_metrics 675 | health_check_grace_period = var.health_check_grace_period 676 | health_check_type = var.health_check_type 677 | load_balancers = var.load_balancer_names 678 | max_size = var.scaling_max 679 | metrics_granularity = "1Minute" 680 | min_size = var.scaling_min 681 | name_prefix = join("-", compact(["AutoScaleGrp", var.name, format("%03d-", count.index + 1)])) 682 | target_group_arns = var.target_group_arns 683 | vpc_zone_identifier = var.subnets 684 | wait_for_capacity_timeout = var.asg_wait_for_capacity_timeout 685 | 686 | launch_template { 687 | id = element(coalescelist( 688 | aws_launch_template.launch_template_with_secondary_ebs.*.id, 689 | aws_launch_template.launch_template_with_no_secondary_ebs.*.id, ), 690 | count.index) 691 | version = "$Latest" 692 | } 693 | 694 | # This block sets tags provided as objects, allowing the propagate at launch field to be set to False 695 | dynamic "tag" { 696 | for_each = var.additional_tags 697 | 698 | content { 699 | key = tag.value.key 700 | value = tag.value.value 701 | propagate_at_launch = lookup(tag.value, "propagate_at_launch", true) 702 | } 703 | } 704 | 705 | # This block sets tags provided as a map in the tags variable (propagated to ASG instances). 706 | dynamic "tag" { 707 | for_each = merge(var.tags, local.tags_ec2, local.tags) 708 | 709 | content { 710 | key = tag.key 711 | value = tag.value 712 | propagate_at_launch = true 713 | } 714 | } 715 | 716 | # This block sets tags provided as a map in the tags_asg variable (not propagated to ASG instances). 717 | dynamic "tag" { 718 | for_each = merge(var.tags_asg, local.tags_asg) 719 | 720 | content { 721 | key = tag.key 722 | value = tag.value 723 | propagate_at_launch = false 724 | } 725 | } 726 | 727 | depends_on = [aws_ssm_association.ssm_bootstrap_assoc] 728 | 729 | lifecycle { 730 | create_before_destroy = true 731 | } 732 | } 733 | 734 | resource "aws_autoscaling_notification" "scaling_notifications" { 735 | count = var.enable_scaling_notification ? var.asg_count : 0 736 | 737 | group_names = [element(aws_autoscaling_group.autoscalegrp.*.name, count.index)] 738 | topic_arn = var.scaling_notification_topic 739 | 740 | notifications = [ 741 | "autoscaling:EC2_INSTANCE_LAUNCH", 742 | "autoscaling:EC2_INSTANCE_LAUNCH_ERROR", 743 | "autoscaling:EC2_INSTANCE_TERMINATE", 744 | "autoscaling:EC2_INSTANCE_TERMINATE_ERROR", 745 | ] 746 | } 747 | 748 | resource "aws_autoscaling_notification" "rs_support_emergency" { 749 | count = var.rackspace_managed ? var.asg_count : 0 750 | 751 | group_names = [element(aws_autoscaling_group.autoscalegrp.*.name, count.index)] 752 | topic_arn = "arn:aws:sns:${data.aws_region.current_region.name}:${data.aws_caller_identity.current_account.account_id}:rackspace-support-emergency" 753 | 754 | notifications = [ 755 | "autoscaling:EC2_INSTANCE_LAUNCH_ERROR", 756 | "autoscaling:EC2_INSTANCE_TERMINATE_ERROR", 757 | ] 758 | } 759 | 760 | # 761 | # Provisioning of CloudWatch related resources 762 | # 763 | 764 | locals { 765 | asg_names = [for n in range(var.asg_count) : element(aws_autoscaling_group.autoscalegrp.*.name, n)] 766 | 767 | alarm_dimensions = tolist([for n in range(var.asg_count) : tomap({ "AutoScalingGroupName" = tostring(local.asg_names[n]) })]) 768 | } 769 | 770 | module "group_terminating_instances" { 771 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-cloudwatch_alarm//?ref=v0.12.6" 772 | 773 | alarm_count = var.asg_count 774 | alarm_description = "Over ${var.terminated_instances} instances terminated in last 6 hours, generating ticket to investigate." 775 | alarm_name = "${var.name}-GroupTerminatingInstances" 776 | comparison_operator = "GreaterThanThreshold" 777 | customer_alarms_cleared = var.customer_alarms_cleared 778 | customer_alarms_enabled = var.customer_alarms_enabled 779 | dimensions = local.alarm_dimensions[*] 780 | evaluation_periods = 1 781 | metric_name = "GroupTerminatingInstances" 782 | namespace = "AWS/AutoScaling" 783 | notification_topic = var.notification_topic 784 | period = 21600 785 | rackspace_alarms_enabled = var.rackspace_alarms_enabled 786 | rackspace_managed = var.rackspace_managed 787 | severity = "emergency" 788 | statistic = "Sum" 789 | threshold = var.terminated_instances 790 | unit = "Count" 791 | } 792 | 793 | resource "aws_cloudwatch_metric_alarm" "scale_alarm_high" { 794 | count = var.policy_type == "SimpleScaling" && var.enable_scaling_actions == true ? var.asg_count : 0 795 | 796 | alarm_actions = [element(aws_autoscaling_policy.ec2_scale_up_policy.*.arn, count.index)] 797 | alarm_description = "Scale-up if ${var.cw_scaling_metric} ${var.cw_high_operator} ${var.cw_high_threshold}% for ${var.cw_high_period} seconds ${var.cw_high_evaluations} times." 798 | alarm_name = join("-", compact(["ScaleAlarmHigh", var.name, format("%03d", count.index + 1)])) 799 | comparison_operator = var.cw_high_operator 800 | evaluation_periods = var.cw_high_evaluations 801 | metric_name = var.cw_scaling_metric 802 | namespace = "AWS/EC2" 803 | period = var.cw_high_period 804 | statistic = "Average" 805 | threshold = var.cw_high_threshold 806 | 807 | dimensions = { 808 | AutoScalingGroupName = element(aws_autoscaling_group.autoscalegrp.*.name, count.index) 809 | } 810 | } 811 | 812 | resource "aws_cloudwatch_metric_alarm" "scale_alarm_low" { 813 | count = var.policy_type == "SimpleScaling" && var.enable_scaling_actions == true ? var.asg_count : 0 814 | 815 | alarm_actions = [element(aws_autoscaling_policy.ec2_scale_down_policy.*.arn, count.index)] 816 | alarm_description = "Scale-down if ${var.cw_scaling_metric} ${var.cw_low_operator} ${var.cw_low_threshold}% for ${var.cw_low_period} seconds ${var.cw_low_evaluations} times." 817 | alarm_name = join("-", compact(["ScaleAlarmLow", var.name, format("%03d", count.index + 1)])) 818 | comparison_operator = var.cw_low_operator 819 | evaluation_periods = var.cw_low_evaluations 820 | metric_name = var.cw_scaling_metric 821 | namespace = "AWS/EC2" 822 | period = var.cw_low_period 823 | statistic = "Average" 824 | threshold = var.cw_low_threshold 825 | 826 | dimensions = { 827 | AutoScalingGroupName = element(aws_autoscaling_group.autoscalegrp.*.name, count.index) 828 | } 829 | } 830 | 831 | resource "aws_cloudwatch_log_group" "system_logs" { 832 | name = "${var.name}-SystemsLogs" 833 | retention_in_days = var.cloudwatch_log_retention 834 | } 835 | 836 | resource "aws_cloudwatch_log_group" "application_logs" { 837 | name = "${var.name}-ApplicationLogs" 838 | retention_in_days = var.cloudwatch_log_retention 839 | } 840 | 841 | # 842 | # Provisioning of SSM related resources 843 | # 844 | 845 | resource "aws_ssm_document" "ssm_bootstrap_doc" { 846 | content = jsonencode(local.ssm_doc_content) 847 | document_format = "JSON" 848 | document_type = "Command" 849 | name = "SSMDocument-${var.name}" 850 | } 851 | 852 | locals { 853 | cwagentparam_vars = { 854 | application_log = aws_cloudwatch_log_group.application_logs.name 855 | system_log = aws_cloudwatch_log_group.system_logs.name 856 | } 857 | 858 | cwagentparam_object = jsondecode(templatefile("${path.module}/text/${local.cwagent_config}", local.cwagentparam_vars)) 859 | } 860 | 861 | resource "aws_ssm_parameter" "cwagentparam" { 862 | count = var.provide_custom_cw_agent_config ? 0 : 1 863 | 864 | description = "${var.name} Cloudwatch Agent configuration" 865 | name = local.cw_config_parameter_name 866 | type = "String" 867 | value = jsonencode(local.cwagentparam_object) 868 | } 869 | 870 | resource "aws_ssm_association" "ssm_bootstrap_assoc" { 871 | name = aws_ssm_document.ssm_bootstrap_doc.name 872 | schedule_expression = var.ssm_association_refresh_rate 873 | 874 | targets { 875 | key = "tag:SSM Target Tag" 876 | values = ["Target-${var.name}"] 877 | } 878 | 879 | depends_on = [aws_ssm_document.ssm_bootstrap_doc] 880 | } 881 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | output "asg_arn_list" { 2 | description = "List of ASG ARNs" 3 | value = aws_autoscaling_group.autoscalegrp.*.arn 4 | } 5 | 6 | output "asg_image_id" { 7 | description = "Image ID used for EC2 provisioning" 8 | value = var.image_id != "" ? var.image_id : data.aws_ami.asg_ami.image_id 9 | } 10 | 11 | output "asg_name_list" { 12 | description = "List of ASG names" 13 | value = aws_autoscaling_group.autoscalegrp.*.name 14 | } 15 | 16 | output "iam_role" { 17 | description = "Name of the created IAM Instance role." 18 | value = element(coalescelist(aws_iam_role.mod_ec2_instance_role.*.id, ["none"]), 0) 19 | } 20 | -------------------------------------------------------------------------------- /tests/test1/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | } 4 | 5 | provider "aws" { 6 | version = "~> 3.0" 7 | region = "us-west-2" 8 | } 9 | 10 | provider "random" { 11 | version = "~> 3.0" 12 | } 13 | 14 | data "aws_region" "current_region" {} 15 | 16 | locals { 17 | tags = merge({ 18 | Environment = "Test" 19 | Purpose = "Testing aws-terraform-ec2_asg" 20 | ServiceProvider = "Rackspace" 21 | Terraform = "true" 22 | }, var.tags) 23 | 24 | tags_asg = { 25 | ASG = "true" 26 | } 27 | } 28 | 29 | resource "random_string" "sqs_rstring" { 30 | length = 18 31 | special = false 32 | upper = false 33 | } 34 | 35 | resource "random_string" "name_rstring" { 36 | length = 8 37 | special = false 38 | } 39 | 40 | module "vpc" { 41 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-vpc_basenetwork?ref=v0.12.7" 42 | 43 | name = "${random_string.name_rstring.result}-ec2-asg-basenetwork-test1" 44 | } 45 | 46 | resource "aws_sqs_queue" "ec2_asg_test_sqs" { 47 | name = "${random_string.sqs_rstring.result}-example-queue" 48 | } 49 | 50 | module "sns" { 51 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-sns?ref=v0.12.2" 52 | 53 | create_subscription_1 = true 54 | endpoint_1 = aws_sqs_queue.ec2_asg_test_sqs.arn 55 | name = "${random_string.sqs_rstring.result}-test-topic" 56 | protocol_1 = "sqs" 57 | } 58 | 59 | module "ec2_asg_centos7_encrypted_test" { 60 | source = "../../module" 61 | 62 | asg_count = 1 63 | ec2_os = "centos7" 64 | enable_scaling_notification = true 65 | encrypt_primary_ebs_volume = true 66 | encrypt_secondary_ebs_volume = true 67 | key_pair = "CircleCI" 68 | name = "${random_string.name_rstring.result}-ec2_asg_centos7_encrypted" 69 | scaling_notification_topic = module.sns.topic_arn 70 | secondary_ebs_volume_size = 60 71 | security_groups = [module.vpc.default_sg] 72 | ssm_patching_group = "Group1Patching" 73 | subnets = slice(module.vpc.public_subnets, 0, 2) 74 | 75 | tags = local.tags 76 | 77 | tags_asg = local.tags_asg 78 | } 79 | 80 | module "ec2_asg_centos7_with_codedeploy_test" { 81 | source = "../../module" 82 | 83 | asg_count = 2 84 | ec2_os = "centos7" 85 | enable_scaling_notification = true 86 | install_codedeploy_agent = true 87 | instance_role_managed_policy_arn_count = 3 88 | key_pair = "CircleCI" 89 | name = "${random_string.name_rstring.result}-ec2_asg_centos7_with_codedeploy" 90 | scaling_notification_topic = module.sns.topic_arn 91 | secondary_ebs_volume_size = 60 92 | security_groups = [module.vpc.default_sg] 93 | ssm_patching_group = "Group1Patching" 94 | subnets = slice(module.vpc.public_subnets, 0, 2) 95 | 96 | instance_role_managed_policy_arns = [ 97 | "arn:aws:iam::aws:policy/AmazonEC2FullAccess", 98 | "arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetTaggingRole", 99 | "arn:aws:iam::aws:policy/CloudWatchActionsEC2Access", 100 | ] 101 | 102 | ssm_bootstrap_list = [ 103 | { 104 | action = "aws:runDocument", 105 | inputs = { 106 | documentPath = "arn:aws:ssm:${data.aws_region.current_region.name}:507897595701:document/Rack-Install_Package", 107 | documentParameters = { 108 | Packages = "bind bindutils" 109 | }, 110 | documentType = "SSMDocument" 111 | }, 112 | name = "InstallBindAndTools", 113 | timeoutSeconds = 300 114 | }, 115 | { 116 | action = "aws:runDocument", 117 | inputs = { 118 | documentPath = "AWS-RunShellScript", 119 | documentParameters = { 120 | commands = ["touch /tmp/myfile"] 121 | }, 122 | documentType = "SSMDocument" 123 | }, 124 | name = "CreateFile", 125 | timeoutSeconds = 300 126 | }, 127 | ] 128 | 129 | tags = local.tags 130 | 131 | tags_asg = local.tags_asg 132 | } 133 | 134 | module "ec2_asg_centos7_no_codedeploy_test" { 135 | source = "../../module" 136 | 137 | ec2_os = "centos7" 138 | enable_scaling_notification = true 139 | install_codedeploy_agent = false 140 | key_pair = "CircleCI" 141 | name = "${random_string.name_rstring.result}-ec2_asg_centos7_no_codedeploy" 142 | scaling_notification_topic = module.sns.topic_arn 143 | secondary_ebs_volume_size = "60" 144 | security_groups = [module.vpc.default_sg] 145 | ssm_patching_group = "Group1Patching" 146 | subnets = slice(module.vpc.public_subnets, 0, 2) 147 | 148 | tags = local.tags 149 | 150 | tags_asg = local.tags_asg 151 | } 152 | 153 | module "ec2_asg_windows_with_codedeploy_test" { 154 | source = "../../module" 155 | 156 | ec2_os = "windows2016" 157 | enable_scaling_actions = false 158 | enable_scaling_notification = true 159 | install_codedeploy_agent = true 160 | instance_role_managed_policy_arn_count = 3 161 | key_pair = "CircleCI" 162 | name = "${random_string.name_rstring.result}-ec2_asg_windows_with_codedeploy" 163 | scaling_notification_topic = module.sns.topic_arn 164 | secondary_ebs_volume_size = 60 165 | security_groups = [module.vpc.default_sg] 166 | ssm_patching_group = "Group1Patching" 167 | subnets = slice(module.vpc.public_subnets, 0, 2) 168 | 169 | instance_role_managed_policy_arns = [ 170 | "arn:aws:iam::aws:policy/AmazonEC2FullAccess", 171 | "arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetTaggingRole", 172 | "arn:aws:iam::aws:policy/CloudWatchActionsEC2Access", 173 | ] 174 | 175 | ssm_bootstrap_list = [ 176 | { 177 | action = "aws:runDocument", 178 | inputs = { 179 | documentPath = "arn:aws:ssm:${data.aws_region.current_region.name}:507897595701:document/Rack-Install_Datadog", 180 | documentType = "SSMDocument" 181 | }, 182 | name = "InstallDataDog", 183 | timeoutSeconds = 300 184 | }, 185 | { 186 | action = "aws:runDocument", 187 | inputs = { 188 | documentPath = "AWS-RunPowerShellScript", 189 | documentParameters = { 190 | commands = ["echo $null >> C:\testfile"] 191 | }, 192 | documentType = "SSMDocument" 193 | }, 194 | name = "CreateFile", 195 | timeoutSeconds = 300 196 | }, 197 | ] 198 | 199 | tags = local.tags 200 | 201 | tags_asg = local.tags_asg 202 | } 203 | 204 | module "ec2_asg_windows_no_codedeploy_test" { 205 | source = "../../module" 206 | 207 | ec2_os = "windows2016" 208 | enable_scaling_actions = false 209 | enable_scaling_notification = true 210 | install_codedeploy_agent = false 211 | key_pair = "CircleCI" 212 | name = "${random_string.name_rstring.result}-ec2_asg_windows_no_codedeploy" 213 | scaling_notification_topic = module.sns.topic_arn 214 | secondary_ebs_volume_size = 60 215 | security_groups = [module.vpc.default_sg] 216 | ssm_patching_group = "Group1Patching" 217 | subnets = slice(module.vpc.public_subnets, 0, 2) 218 | 219 | tags = local.tags 220 | 221 | tags_asg = local.tags_asg 222 | } 223 | 224 | module "ec2_asg_amazon2023_no_codedeploy_test" { 225 | source = "../../module" 226 | 227 | ec2_os = "amazon2023" 228 | enable_scaling_notification = true 229 | install_codedeploy_agent = false 230 | key_pair = "CircleCI" 231 | name = "${random_string.name_rstring.result}-ec2_asg_amazon2023_no_codedeploy" 232 | scaling_notification_topic = module.sns.topic_arn 233 | secondary_ebs_volume_size = "60" 234 | security_groups = [module.vpc.default_sg] 235 | ssm_patching_group = "Group1Patching" 236 | subnets = slice(module.vpc.public_subnets, 0, 2) 237 | 238 | tags = local.tags 239 | 240 | tags_asg = local.tags_asg 241 | } 242 | -------------------------------------------------------------------------------- /tests/test1/variables.tf: -------------------------------------------------------------------------------- 1 | variable "tags" { 2 | description = "Custom tags to apply to all resources." 3 | type = map(string) 4 | default = {} 5 | } 6 | -------------------------------------------------------------------------------- /text/amazon_linux_userdata.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ${initial_commands} 4 | 5 | # Ensure SSM installed on Amazon Linux 6 | # in cases where it is not available / removed 7 | ssm_running=$( ps -ef | grep ['a']mazon-ssm-agent | wc -l ) 8 | if [[ $ssm_running != "0" ]]; then 9 | echo -e "amazon-ssm-agent already running" 10 | else 11 | if [[ -r "/tmp/ssm_agent_install" ]]; then : ; 12 | else mkdir -p /tmp/ssm_agent_install; fi 13 | curl https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm -o /tmp/ssm_agent_install/amazon-ssm-agent.rpm 14 | rpm -Uvh /tmp/ssm_agent_install/amazon-ssm-agent.rpm 15 | ssm_running=$( ps -ef | grep ['a']mazon-ssm-agent | wc -l ) 16 | # Amazon Linux 2 17 | systemctl=$( command -v systemctl | wc -l ) 18 | if [[ $systemctl != "0" ]]; then 19 | systemctl enable amazon-ssm-agent 20 | if [[ $ssm_running == "0" ]]; then 21 | systemctl start amazon-ssm-agent 22 | fi 23 | fi 24 | fi 25 | 26 | ${final_commands} 27 | -------------------------------------------------------------------------------- /text/debian_userdata.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | function lock_wait { 4 | endtime=$(( $(date +%s) + 300 )) 5 | set +e 6 | while [ $(date +%s) -lt $endtime ]; do 7 | "$@" && break 8 | sleep 15 9 | done 10 | set -e 11 | } 12 | 13 | function install_ssm_deb { 14 | if [[ -r "/tmp/ssm_agent_install" ]]; then : ; 15 | else 16 | mkdir -p /tmp/ssm_agent_install 17 | fi 18 | curl https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/debian_amd64/amazon-ssm-agent.deb -o /tmp/ssm_agent_install/amazon-ssm-agent.deb 19 | lock_wait dpkg -i /tmp/ssm_agent_install/amazon-ssm-agent.deb 20 | 21 | if ps -ef | grep -q [a]mazon-ssm-agent ;then 22 | ssm_running="yes" 23 | else 24 | ssm_running="no" 25 | fi 26 | 27 | if command -v systemctl ; then 28 | systemctl enable amazon-ssm-agent 29 | if [[ $ssm_running == "no" ]]; then 30 | systemctl start amazon-ssm-agent 31 | fi 32 | else 33 | if [[ $ssm_running == "no" ]]; then 34 | start amazon-ssm-agent 35 | fi 36 | fi 37 | 38 | return 0 39 | } 40 | 41 | function install_aws_cli_v2 { 42 | mkdir -p /opt/aws/aws 43 | curl https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o /opt/aws/awscliv2.zip && \ 44 | unzip -o /opt/aws/awscliv2.zip -d /opt/aws && \ 45 | /opt/aws/aws/install -u 46 | } 47 | 48 | export LC_ALL=C.UTF-8 49 | export DEBIAN_FRONTEND=noninteractive 50 | 51 | ${initial_commands} 52 | 53 | exec 1> >(logger -s -t $(basename $0)) 2>&1 54 | 55 | lock_wait apt-get update 56 | lock_wait apt-get -y install python-setuptools python3-pip unzip 57 | 58 | # Install AWSCLIv2 59 | install_aws_cli_v2 60 | 61 | if ps -ef | grep -q [a]mazon-ssm-agent ;then 62 | ssm_running="yes" 63 | else 64 | ssm_running="no" 65 | fi 66 | 67 | if [[ $ssm_running == "yes" ]]; then 68 | echo "amazon-ssm-agent already running" 69 | else 70 | # use deb installer 71 | install_ssm_deb 72 | fi -------------------------------------------------------------------------------- /text/linux_cw_agent_param.json: -------------------------------------------------------------------------------- 1 | { 2 | "metrics": { 3 | "append_dimensions": { 4 | "InstanceId": "$${aws:InstanceId}" 5 | }, 6 | "aggregation_dimensions": [ 7 | ["InstanceId"], 8 | ["InstanceId", "device"] 9 | ], 10 | "metrics_collected": { 11 | "mem": { 12 | "metrics_collection_interval": 60, 13 | "measurement": ["used_percent"] 14 | }, 15 | "disk": { 16 | "ignore_file_system_types": [ 17 | "devtmpfs", 18 | "tmpfs", 19 | "devfs", 20 | "rootfs", 21 | "squashfs" 22 | ], 23 | "metrics_collection_interval": 60, 24 | "resources": ["*"], 25 | "measurement": [ 26 | "used_percent", 27 | "disk_total", 28 | "disk_used" 29 | ] 30 | } 31 | } 32 | }, 33 | "logs": { 34 | "force_flush_interval": 60, 35 | "logs_collected": { 36 | "files": { 37 | "collect_list": [ 38 | { 39 | "file_path": "/var/log/cloud-init-output.log", 40 | "log_group_name": "${system_log}", 41 | "log_stream_name": "{instance_id}/cloud-init-output.log" 42 | }, 43 | { 44 | "timestamp_format": "%b %d %H:%M:%S", 45 | "file_path": "/var/log/cloud-init.log", 46 | "log_group_name": "${system_log}", 47 | "log_stream_name": "{instance_id}/cloud-init.log" 48 | }, 49 | { 50 | "timestamp_format": "%Y-%m-%d %H:%M:%S", 51 | "multi_line_start_pattern": "{timestamp_format}", 52 | "file_path": "/var/log/amazon/ssm/amazon-ssm-agent.log", 53 | "log_group_name": "${system_log}", 54 | "log_stream_name": "{instance_id}/amazon-ssm-agent.log" 55 | }, 56 | { 57 | "timestamp_format": "%Y-%m-%d %H:%M:%S", 58 | "multi_line_start_pattern": "{timestamp_format}", 59 | "file_path": "/var/log/amazon/ssm/errors.log", 60 | "log_group_name": "${system_log}", 61 | "log_stream_name": "{instance_id}/amazon-ssm-errors.log" 62 | }, 63 | { 64 | "timestamp_format": "%d/%b/%Y:%H:%M:%S", 65 | "file_path": "/var/log/httpd/access*", 66 | "log_group_name": "${application_log}", 67 | "log_stream_name": "{instance_id}/httpd-access" 68 | }, 69 | { 70 | "timestamp_format": "%d/%b/%Y:%H:%M:%S", 71 | "file_path": "/var/log/httpd/error*", 72 | "log_group_name": "${application_log}", 73 | "log_stream_name": "{instance_id}/httpd-error" 74 | }, 75 | { 76 | "timestamp_format": "%d/%b/%Y:%H:%M:%S", 77 | "file_path": "/var/log/apache2/access*", 78 | "log_group_name": "${application_log}", 79 | "log_stream_name": "{instance_id}/apache2-access" 80 | }, 81 | { 82 | "timestamp_format": "%d/%b/%Y:%H:%M:%S", 83 | "file_path": "/var/log/apache2/error*", 84 | "log_group_name": "${application_log}", 85 | "log_stream_name": "{instance_id}/apache2-error" 86 | }, 87 | { 88 | "timestamp_format": "%d/%b/%Y:%H:%M:%S", 89 | "file_path": "/var/log/nginx/access*", 90 | "log_group_name": "${application_log}", 91 | "log_stream_name": "{instance_id}/nginx-access" 92 | }, 93 | { 94 | "timestamp_format": "%d/%b/%Y:%H:%M:%S", 95 | "file_path": "/var/log/nginx/error*", 96 | "log_group_name": "${application_log}", 97 | "log_stream_name": "{instance_id}/nginx-error" 98 | } 99 | ] 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /text/rhel_centos_7_userdata.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | ${initial_commands} 4 | 5 | exec 1> >(logger -s -t $(basename $0)) 2>&1 6 | 7 | curl https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -o /tmp/epel-release-latest-7.noarch.rpm 8 | rpm -qa | grep -q epel-release || yum install -y /tmp/epel-release-latest-7.noarch.rpm 9 | 10 | #install awscliv2 11 | yum install -y unzip 12 | mkdir -p /tmp/awscliv2 13 | curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "/tmp/awscliv2/awscliv2.zip" 14 | unzip /tmp/awscliv2/awscliv2.zip -d /tmp/awscliv2/ 15 | ./tmp/awscliv2/aws/install 16 | 17 | ssm_running=$( ps -ef | grep [a]mazon-ssm-agent | wc -l ) 18 | if [[ $ssm_running != "0" ]]; then 19 | echo -e "amazon-ssm-agent already running" 20 | else 21 | if [[ -r "/tmp/ssm_agent_install" ]]; then : ; 22 | else mkdir -p /tmp/ssm_agent_install; fi 23 | curl https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm -o /tmp/ssm_agent_install/amazon-ssm-agent.rpm 24 | rpm -Uvh /tmp/ssm_agent_install/amazon-ssm-agent.rpm 25 | ssm_running=$( ps -ef | grep [a]mazon-ssm-agent | wc -l ) 26 | systemctl=$( command -v systemctl | wc -l ) 27 | if [[ $systemctl != "0" ]]; then 28 | systemctl enable amazon-ssm-agent 29 | if [[ $ssm_running == "0" ]]; then 30 | systemctl start amazon-ssm-agent 31 | fi 32 | else 33 | if [[ $ssm_running == "0" ]]; then 34 | start amazon-ssm-agent 35 | fi 36 | fi 37 | fi 38 | 39 | ${final_commands} 40 | -------------------------------------------------------------------------------- /text/rhel_centos_8_userdata.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | ${initial_commands} 4 | 5 | exec 1> >(logger -s -t $(basename $0)) 2>&1 6 | 7 | curl https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -o /tmp/epel-release-latest-8.noarch.rpm 8 | rpm -qa | grep -q epel-release || yum install -y /tmp/epel-release-latest-8.noarch.rpm 9 | 10 | #install awscliv2 11 | dnf makecache 12 | dnf -y install unzip 13 | mkdir -p /tmp/awscliv2 14 | curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "/tmp/awscliv2/awscliv2.zip" 15 | unzip /tmp/awscliv2/awscliv2.zip -d /tmp/awscliv2/ 16 | ./tmp/awscliv2/aws/install 17 | 18 | ssm_running=$( ps -ef | grep [a]mazon-ssm-agent | wc -l ) 19 | if [[ $ssm_running != "0" ]]; then 20 | echo -e "amazon-ssm-agent already running" 21 | exit 0 22 | else 23 | dnf install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm 24 | ssm_running=$( ps -ef | grep [a]mazon-ssm-agent | wc -l ) 25 | systemctl=$( command -v systemctl | wc -l ) 26 | if [[ $systemctl != "0" ]]; then 27 | systemctl enable amazon-ssm-agent 28 | if [[ $ssm_running == "0" ]]; then 29 | systemctl start amazon-ssm-agent 30 | fi 31 | else 32 | if [[ $ssm_running == "0" ]]; then 33 | start amazon-ssm-agent 34 | fi 35 | fi 36 | fi 37 | 38 | ${final_commands} 39 | -------------------------------------------------------------------------------- /text/ubuntu_userdata.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | function lock_wait { 4 | endtime=$(( $(date +%s) + 300 )) 5 | set +e 6 | while [ $(date +%s) -lt $endtime ]; do 7 | "$@" && break 8 | sleep 15 9 | done 10 | set -e 11 | } 12 | 13 | function install_ssm_deb { 14 | if [[ -r "/tmp/ssm_agent_install" ]]; then : ; 15 | else 16 | mkdir -p /tmp/ssm_agent_install 17 | fi 18 | curl https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/debian_amd64/amazon-ssm-agent.deb -o /tmp/ssm_agent_install/amazon-ssm-agent.deb 19 | lock_wait dpkg -i /tmp/ssm_agent_install/amazon-ssm-agent.deb 20 | 21 | if ps -ef | grep -q [a]mazon-ssm-agent ;then 22 | ssm_running="yes" 23 | else 24 | ssm_running="no" 25 | fi 26 | 27 | if command -v systemctl ; then 28 | systemctl enable amazon-ssm-agent 29 | if [[ $ssm_running == "no" ]]; then 30 | systemctl start amazon-ssm-agent 31 | fi 32 | else 33 | if [[ $ssm_running == "no" ]]; then 34 | start amazon-ssm-agent 35 | fi 36 | fi 37 | 38 | return 0 39 | } 40 | 41 | function install_ssm_snap { 42 | if snap install amazon-ssm-agent --classic; then 43 | echo "snap should be installed" 44 | snap list amazon-ssm-agent 45 | else 46 | # handle case where it actually installed but timed out 47 | systemctl start snap.amazon-ssm-agent.amazon-ssm-agent.service 48 | systemctl stop snap.amazon-ssm-agent.amazon-ssm-agent.service 49 | snap start amazon-ssm-agent --enable 50 | fi 51 | return 0 52 | } 53 | 54 | export LC_ALL=C.UTF-8 55 | export DEBIAN_FRONTEND=noninteractive 56 | lock_wait apt-get update 57 | 58 | ${initial_commands} 59 | 60 | exec 1> >(logger -s -t $(basename $0)) 2>&1 61 | 62 | #install awscliv2 63 | lock_wait apt-get install unzip 64 | mkdir -p /tmp/awscliv2 65 | curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "/tmp/awscliv2/awscliv2.zip" 66 | unzip /tmp/awscliv2/awscliv2.zip -d /tmp/awscliv2/ 67 | ./tmp/awscliv2/aws/install 68 | 69 | 70 | 71 | if ps -ef | grep -q [a]mazon-ssm-agent ;then 72 | ssm_running="yes" 73 | else 74 | ssm_running="no" 75 | fi 76 | 77 | if [[ $ssm_running == "yes" ]]; then 78 | echo "amazon-ssm-agent already running" 79 | else 80 | source /etc/os-release 81 | #always uses snap for 18.04 and higher 82 | if snap list amazon-ssm-agent | grep -q amazon-ssm-agent ; then 83 | echo "snap is installed ... starting" 84 | snap start amazon-ssm-agent 85 | else 86 | install_ssm_snap 87 | fi 88 | fi 89 | 90 | ${final_commands} 91 | -------------------------------------------------------------------------------- /text/windows_cw_agent_param.json: -------------------------------------------------------------------------------- 1 | { 2 | "logs": { 3 | "force_flush_interval": 60, 4 | "logs_collected": { 5 | "files": { 6 | "collect_list": [ 7 | { 8 | "file_path": "C:\\Program Files\\Amazon\\Ec2ConfigService\\Logs\\Ec2Configlog.txt", 9 | "log_group_name": "${system_log}", 10 | "log_stream_name": "{instance_id}/Ec2Config.log", 11 | "timestamp_format": "%Y-%m-%dT%H:%M:%S", 12 | "multi_line_start_pattern": "{timestamp_format}" 13 | }, 14 | { 15 | "file_path": "c:\\ProgramData\\Amazon\\SSM\\Logs\\amazon-ssm-agent.log", 16 | "log_group_name": "${system_log}", 17 | "log_stream_name": "{instance_id}/amazon-ssm-agent.log", 18 | "timestamp_format": "%Y-%m-%d %H:%M:%S", 19 | "multi_line_start_pattern": "{timestamp_format}" 20 | }, 21 | { 22 | "file_path": "c:\\ProgramData\\Amazon\\SSM\\Logs\\errors.log", 23 | "log_group_name": "${system_log}", 24 | "log_stream_name": "{instance_id}/amazon-ssm-errors.log", 25 | "timestamp_format": "%Y-%m-%d %H:%M:%S", 26 | "multi_line_start_pattern": "{timestamp_format}" 27 | }, 28 | { 29 | "file_path": "C:\\inetpub\\logs\\LogFiles\\W3SVC1\\*.log", 30 | "log_group_name": "${application_log}", 31 | "log_stream_name": "{instance_id}/IISLogs", 32 | "timestamp_format": "%Y-%m-%d %H:%M:%S" 33 | } 34 | ] 35 | }, 36 | "windows_events": { 37 | "collect_list": [ 38 | { 39 | "event_name": "System", 40 | "event_levels": ["INFORMATION", "WARNING", "ERROR", "CRITICAL"], 41 | "log_group_name": "${system_log}", 42 | "log_stream_name": "{instance_id}/System" 43 | }, 44 | { 45 | "event_name": "Application", 46 | "event_levels": ["INFORMATION", "WARNING", "ERROR", "CRITICAL"], 47 | "log_group_name": "${system_log}", 48 | "log_stream_name": "{instance_id}/Application" 49 | }, 50 | { 51 | "event_name": "Security", 52 | "event_levels": ["INFORMATION", "WARNING", "ERROR", "CRITICAL"], 53 | "log_group_name": "${system_log}", 54 | "log_stream_name": "{instance_id}/Security" 55 | } 56 | ] 57 | } 58 | } 59 | }, 60 | "metrics": { 61 | "append_dimensions": { 62 | "InstanceId": "$${aws:InstanceId}" 63 | }, 64 | "aggregation_dimensions": [["InstanceId"]], 65 | "metrics_collected": { 66 | "LogicalDisk": { 67 | "measurement": [{ "name": "% Free Space"}], 68 | "metrics_collection_interval": 60, 69 | "resources": ["*"] 70 | }, 71 | "Memory": { 72 | "measurement": ["Available MBytes", {"name": "% Committed Bytes In Use"}], 73 | "metrics_collection_interval": 60 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /text/windows_userdata.ps1: -------------------------------------------------------------------------------- 1 | 2 | ${initial_commands} 3 | 4 | ${final_commands} 5 | 6 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "additional_ssm_bootstrap_list" { 2 | description = "A list of maps consisting of main step actions, to be appended to SSM associations. Please see usage.tf.example in this repo for examples.

(DEPRECATED) This variable will be removed in future releases in favor of the `ssm_bootstrap_list` variable." 3 | type = list(map(string)) 4 | default = [] 5 | } 6 | 7 | variable "additional_tags" { 8 | description = "Additional tags to be added to the ASG instance(s). Format: list of maps. Please see usage.tf.example in this repo for examples.

(DEPRECATED) This variable will be removed in future releases in favor of the `tags` and `tags_asg` variables." 9 | type = list(map(string)) 10 | default = [] 11 | } 12 | 13 | variable "alb_resource_label" { 14 | description = "Enter the ALB and Target group in this format : app/load-balancer-name/load-balancer-id/targetgroup/target-group-name/target-group-id" 15 | type = string 16 | default = null 17 | } 18 | 19 | variable "asg_count" { 20 | description = "Number of identical ASG's to deploy" 21 | type = string 22 | default = "1" 23 | } 24 | 25 | variable "asg_wait_for_capacity_timeout" { 26 | description = "A maximum duration that Terraform should wait for ASG instances to be healthy before timing out." 27 | type = string 28 | default = "10m" 29 | } 30 | 31 | variable "backup_tag_value" { 32 | description = "Value of the 'Backup' tag, used to assign to the AWS Backup configuration" 33 | type = string 34 | default = "False" 35 | } 36 | 37 | variable "cloudwatch_log_retention" { 38 | description = "The number of days to retain Cloudwatch Logs for this instance." 39 | type = string 40 | default = "30" 41 | } 42 | 43 | variable "customer_alarms_cleared" { 44 | description = "Specifies whether alarms will notify customers when returning to an OK status." 45 | type = bool 46 | default = false 47 | } 48 | 49 | variable "customer_alarms_enabled" { 50 | description = "Specifies whether alarms will notify customers. Automatically enabled if rackspace_managed is set to false" 51 | type = bool 52 | default = false 53 | } 54 | 55 | variable "custom_cw_agent_config_ssm_param" { 56 | description = "SSM Parameter Store name that contains a custom CloudWatch agent configuration that you would like to use as an alternative to the default provided." 57 | type = string 58 | default = "" 59 | } 60 | 61 | variable "cw_high_evaluations" { 62 | description = "The number of periods over which data is compared to the specified threshold." 63 | type = string 64 | default = "3" 65 | } 66 | 67 | variable "cw_high_operator" { 68 | description = "Math operator used by CloudWatch for alarms and triggers." 69 | type = string 70 | default = "GreaterThanThreshold" 71 | } 72 | 73 | variable "cw_high_period" { 74 | description = "Time the specified statistic is applied. Must be in seconds that is also a multiple of 60." 75 | type = string 76 | default = "60" 77 | } 78 | 79 | variable "cw_high_threshold" { 80 | description = "The value against which the specified statistic is compared." 81 | type = string 82 | default = "60" 83 | } 84 | 85 | variable "cw_low_evaluations" { 86 | description = "The number of periods over which data is compared to the specified threshold." 87 | type = string 88 | default = "3" 89 | } 90 | 91 | variable "cw_low_operator" { 92 | description = "Math operator used by CloudWatch for alarms and triggers." 93 | type = string 94 | default = "LessThanThreshold" 95 | } 96 | 97 | variable "cw_low_period" { 98 | description = "Time the specified statistic is applied. Must be in seconds that is also a multiple of 60." 99 | type = string 100 | default = "300" 101 | } 102 | 103 | variable "cw_low_threshold" { 104 | description = "The value against which the specified statistic is compared." 105 | type = string 106 | default = "30" 107 | } 108 | 109 | variable "cw_scaling_metric" { 110 | description = "The metric to be used for scaling." 111 | type = string 112 | default = "CPUUtilization" 113 | } 114 | 115 | variable "detailed_monitoring" { 116 | description = "Enable Detailed Monitoring? true or false" 117 | type = bool 118 | default = true 119 | } 120 | 121 | variable "disable_scale_in" { 122 | description = "Disable scale in to create only a scale-out policy in Target Tracking Policy." 123 | type = bool 124 | default = false 125 | } 126 | 127 | variable "ec2_os" { 128 | description = "Intended Operating System/Distribution of Instance. Valid inputs are: `amazon2`, `amazoneks`, `amazonecs`, `rhel7`, `rhel8`, `centos7`, `ubuntu18`, `ubuntu20`, `windows2012r2`, `windows2016`, `windows2019`" 129 | type = string 130 | } 131 | 132 | variable "ec2_scale_down_adjustment" { 133 | description = "Number of EC2 instances to scale down by at a time. Positive numbers will be converted to negative." 134 | type = string 135 | default = "-1" 136 | } 137 | 138 | variable "ec2_scale_down_cool_down" { 139 | description = "Time in seconds before any further trigger-related scaling can occur." 140 | type = string 141 | default = "60" 142 | } 143 | 144 | variable "ec2_scale_up_adjustment" { 145 | description = "Number of EC2 instances to scale up by at a time." 146 | type = string 147 | default = "1" 148 | } 149 | 150 | variable "ec2_scale_up_cool_down" { 151 | description = "Time in seconds before any further trigger-related scaling can occur." 152 | type = string 153 | default = "60" 154 | } 155 | 156 | variable "enable_ebs_optimization" { 157 | description = "Use EBS Optimized? true or false" 158 | type = bool 159 | default = false 160 | } 161 | 162 | variable "enable_rolling_updates" { 163 | description = "Should this autoscaling group be targeted by the ASG Instance Replacement tool to ensure all instances are using thelatest launch configuration." 164 | type = bool 165 | default = true 166 | } 167 | 168 | variable "enable_scaling_actions" { 169 | description = "Should this autoscaling group be configured with scaling alarms to manage the desired count. Set this variable to false if another process will manage the desired count, such as EKS Cluster Autoscaler." 170 | type = bool 171 | default = true 172 | } 173 | 174 | variable "enable_scaling_notification" { 175 | description = "true or false. If 'scaling_notification_topic' is set to a non-empty string, this must be set to true. Otherwise, set to false. This variable exists due to a terraform limitation with using count and computed values as conditionals" 176 | type = bool 177 | default = false 178 | } 179 | 180 | variable "enabled_asg_metrics" { 181 | description = "List of ASG metrics desired. This can only contain the following values: `GroupDesiredCapacity`, `GroupInServiceCapacity`, `GroupPendingCapacity`, `GroupMinSize`, `GroupMaxSize`, `GroupInServiceInstances`, `GroupPendingInstances`, `GroupStandbyInstances`, `GroupStandbyCapacity`, `GroupTerminatingCapacity`, `GroupTerminatingInstances`, `GroupTotalCapacity`, `GroupTotalInstances`." 182 | type = list(string) 183 | default = [] 184 | } 185 | 186 | variable "encrypt_primary_ebs_volume" { 187 | description = "Encrypt root EBS Volume? true or false" 188 | type = bool 189 | default = false 190 | } 191 | 192 | variable "encrypt_secondary_ebs_volume" { 193 | description = "Encrypt secondary EBS Volume? true or false" 194 | type = bool 195 | default = false 196 | } 197 | 198 | variable "environment" { 199 | description = "Application environment for which this network is being created. Preferred value are Development, Integration, PreProduction, Production, QA, Staging, or Test" 200 | type = string 201 | default = "Development" 202 | } 203 | 204 | variable "final_userdata_commands" { 205 | description = "Commands to be given at the end of userdata for an instance. This should generally not include bootstrapping or ssm install." 206 | type = string 207 | default = "" 208 | } 209 | 210 | variable "health_check_grace_period" { 211 | description = "Number of seconds grace during which no autoscaling actions will be taken." 212 | type = string 213 | default = "300" 214 | } 215 | 216 | variable "health_check_type" { 217 | description = "Define the type of healthcheck for the AutoScaling group." 218 | type = string 219 | default = "EC2" 220 | } 221 | 222 | variable "image_id" { 223 | description = "The AMI ID to be used to build the EC2 Instance. If not provided, an AMI ID will be queried with an OS specified in variable ec2_os." 224 | type = string 225 | default = "" 226 | } 227 | 228 | variable "initial_userdata_commands" { 229 | description = "Commands to be given at the start of userdata for an instance. This should generally not include bootstrapping or ssm install." 230 | type = string 231 | default = "" 232 | } 233 | 234 | variable "install_codedeploy_agent" { 235 | description = "Install codedeploy agent on instance(s)? true or false" 236 | type = bool 237 | default = false 238 | } 239 | 240 | variable "instance_profile_override" { 241 | description = "Optionally provide an instance profile. Any override profile should contain the permissions required for Rackspace support tooling to continue to function if required." 242 | type = bool 243 | default = false 244 | } 245 | 246 | variable "instance_profile_override_name" { 247 | description = "Provide an instance profile name. Any override profile should contain the permissions required for Rackspace support tooling to continue to function if required. To use this set `instance_profile_override` to `true`." 248 | type = string 249 | default = "" 250 | } 251 | 252 | variable "instance_role_managed_policy_arn_count" { 253 | description = "The number of policy ARNs provided/set in variable 'instance_role_managed_policy_arns'" 254 | type = string 255 | default = "0" 256 | } 257 | 258 | variable "instance_role_managed_policy_arns" { 259 | description = "List of IAM policy ARNs for the InstanceRole IAM role. IAM ARNs can be found within the Policies section of the AWS IAM console. e.g. ['arn:aws:iam::aws:policy/AmazonEC2FullAccess', 'arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore', 'arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetRole']" 260 | type = list(string) 261 | default = [] 262 | } 263 | 264 | variable "instance_type" { 265 | description = "EC2 Instance Type e.g. 't2.micro'" 266 | type = string 267 | default = "t2.micro" 268 | } 269 | 270 | variable "instance_warm_up_time" { 271 | description = "Specify the Instance Warm Up time for Target Tracking Policy." 272 | type = string 273 | default = "300" 274 | } 275 | 276 | variable "key_pair" { 277 | description = "Name of an existing EC2 KeyPair to enable SSH access to the instances." 278 | type = string 279 | default = "" 280 | } 281 | 282 | variable "load_balancer_names" { 283 | description = "A list of Classic load balancers associated with this Auto Scaling group." 284 | type = list(string) 285 | default = [] 286 | } 287 | 288 | variable "name" { 289 | description = "Name to be used for the provisioned EC2 instance(s), ASG(s), and other resources provisioned in this module" 290 | type = string 291 | } 292 | 293 | variable "notification_topic" { 294 | description = "List of SNS Topic ARNs to use for customer notifications." 295 | type = list(string) 296 | default = [] 297 | } 298 | 299 | variable "perform_ssm_inventory_tag" { 300 | description = "Determines whether Instance is tracked via System Manager Inventory." 301 | type = string 302 | default = "True" 303 | } 304 | 305 | variable "policy_type" { 306 | description = "Enter scaling policy type. Allowed values are : SimpleScaling or TargetTrackingScaling" 307 | type = string 308 | default = "SimpleScaling" 309 | } 310 | 311 | variable "primary_ebs_volume_iops" { 312 | description = "Iops value required for use with io1 EBS volumes. This value should be 3 times the EBS volume size" 313 | type = string 314 | default = "0" 315 | } 316 | 317 | variable "primary_ebs_volume_size" { 318 | description = "EBS Volume Size in GB" 319 | type = string 320 | default = "60" 321 | } 322 | 323 | variable "primary_ebs_volume_type" { 324 | description = "EBS Volume Type. e.g. gp2, io1, st1, sc1" 325 | type = string 326 | default = "gp2" 327 | } 328 | 329 | variable "provide_custom_cw_agent_config" { 330 | description = "Set to true if a custom cloudwatch agent configuration has been provided in variable custom_cw_agent_config_ssm_param." 331 | type = bool 332 | default = false 333 | } 334 | 335 | variable "rackspace_alarms_enabled" { 336 | description = "Specifies whether alarms will create a Rackspace ticket. Ignored if rackspace_managed is set to false." 337 | type = bool 338 | default = false 339 | } 340 | 341 | variable "rackspace_managed" { 342 | description = "Boolean parameter controlling if instance will be fully managed by Rackspace support teams, created CloudWatch alarms that generate tickets, and utilize Rackspace managed SSM documents." 343 | type = bool 344 | default = true 345 | } 346 | 347 | variable "scaling_max" { 348 | description = "The maximum size of the Auto Scaling group." 349 | type = string 350 | default = "2" 351 | } 352 | 353 | variable "scaling_min" { 354 | description = "The minimum count of EC2 instances in the Auto Scaling group." 355 | type = string 356 | default = "1" 357 | } 358 | 359 | variable "scaling_notification_topic" { 360 | description = "SNS Topic ARN to notify if there are any scaling operations. OPTIONAL" 361 | type = string 362 | default = "" 363 | } 364 | 365 | variable "secondary_ebs_volume_existing_id" { 366 | description = "The Snapshot ID of an existing EBS volume you want to use for the secondary volume. i.e. snap-0ad8580e3ac34a9f1" 367 | type = string 368 | default = "" 369 | } 370 | 371 | variable "secondary_ebs_volume_iops" { 372 | description = "Iops value required for use with io1 EBS volumes. This value should be 3 times the EBS volume size" 373 | type = string 374 | default = "0" 375 | } 376 | 377 | variable "secondary_ebs_volume_size" { 378 | description = "EBS Volume Size in GB" 379 | type = string 380 | default = "" 381 | } 382 | 383 | variable "secondary_ebs_volume_type" { 384 | description = "EBS Volume Type. e.g. gp2, io1, st1, sc1" 385 | type = string 386 | default = "gp2" 387 | } 388 | 389 | variable "security_groups" { 390 | description = "A list of EC2 security IDs to assign to this resource." 391 | type = list(string) 392 | } 393 | 394 | variable "ssm_association_refresh_rate" { 395 | description = "A cron or rate pattern to define the SSM Association refresh schedule, defaulting to once per day. See https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-cron.html for more details. Schedule can be disabled by providing an empty string." 396 | type = string 397 | default = "rate(1 day)" 398 | } 399 | 400 | variable "ssm_bootstrap_list" { 401 | description = "A list of objects consisting of actions, to be appended to SSM associations. Please see usage.tf.example in this repo for examples." 402 | type = any 403 | default = [] 404 | } 405 | 406 | variable "ssm_patching_group" { 407 | description = "Group ID to be used by System Manager for Patching" 408 | type = string 409 | default = "" 410 | } 411 | 412 | variable "subnets" { 413 | description = "List of subnets for Application. e.g. ['subnet-8da92df7', 'subnet-9e5dc5f6', 'subnet-497eaf33']" 414 | type = list(string) 415 | } 416 | 417 | variable "tags" { 418 | description = "A map of tags to apply to all resources. These tags will all be propagated to ASG instances and set on all other resources." 419 | type = map(string) 420 | default = {} 421 | } 422 | 423 | variable "tags_asg" { 424 | description = "A map of tags to apply to the ASG itself. These tags will not be propagated to ASG instances or set on any other resources." 425 | type = map(string) 426 | default = {} 427 | } 428 | 429 | variable "target_group_arns" { 430 | description = "A list of Amazon Resource Names (ARN) of target groups to associate with the Auto Scaling group." 431 | type = list(string) 432 | default = [] 433 | } 434 | 435 | variable "target_value" { 436 | description = "Enter the target value for Target Scaling Policy metrics." 437 | type = string 438 | default = "50" 439 | } 440 | 441 | variable "tenancy" { 442 | description = "The placement tenancy for EC2 devices. e.g. host, default, dedicated" 443 | type = string 444 | default = "default" 445 | } 446 | 447 | variable "terminated_instances" { 448 | description = "Specifies the maximum number of instances that can be terminated in a six hour period without generating a Cloudwatch Alarm." 449 | type = string 450 | default = "30" 451 | } 452 | 453 | variable "tracking_policy_metric" { 454 | description = "Allowed Values are: ASGAverageCPUUtilization, ASGAverageNetworkIn, ASGAverageNetworkOut, ALBRequestCountPerTarget" 455 | type = string 456 | default = "ASGAverageCPUUtilization" 457 | } 458 | variable "metadata_http_endpoint" { 459 | description = "Whether the metadata service is available. Valid values include enabled or disabled." 460 | type = string 461 | default = "enabled" 462 | } 463 | 464 | variable "metadata_http_put_response_hop_limit" { 465 | description = " Desired HTTP PUT response hop limit for instance metadata requests. The larger the number, the further instance metadata requests can travel. Valid values are integer from 1 to 64" 466 | type = number 467 | default = 1 468 | } 469 | 470 | variable "metadata_http_tokens" { 471 | description = "Whether or not the metadata service requires session tokens, also referred to as Instance Metadata Service Version 2 (IMDSv2). Valid values include optional or required." 472 | type = string 473 | default = "optional" 474 | } 475 | 476 | variable "metadata_instance_metadata_tags" { 477 | description = "Enables or disables access to instance tags from the instance metadata service. Valid values include enabled or disabled" 478 | type = string 479 | default = "disabled" 480 | } 481 | --------------------------------------------------------------------------------