Skip to content

Commit b2bc692

Browse files
committed
lots of progress on the documentation
1 parent 7dae913 commit b2bc692

File tree

2 files changed

+178
-14
lines changed

2 files changed

+178
-14
lines changed

README.md

Lines changed: 177 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,55 @@ This module uses CodeDeploy to deploy a Lambda behind an ALB.
99

1010
Before switching production traffic to the new Lambda, CodeDeploy runs Postman tests.
1111
This is done by:
12-
* Having all production traffic (ports `80`/`443`) sent to the Lambda considered `live`
13-
* Creating and deploying the new untested Lambda to `$LATEST`
14-
* Invoking a separate Lambda that runs Postman tests
15-
- These tests run against port `4443`, which corresponds to `$LATEST`
12+
* Having all production traffic (port `443`) sent to the Lambda version considered `live`
13+
* Creating and deploying the new untested Lambda version to `$LATEST`
14+
* Invoking a separate "test" Lambda that runs Postman tests
15+
- These tests run against the port specified by `codedeploy_test_listener_port`, which corresponds to `$LATEST`
1616
* If the tests pass, we give the alias `live` to the now-tested `$LATEST` version of the Lambda
1717

1818
## Usage
1919
```hcl
20+
module "lambda_api" {
21+
source = "../../"
22+
app_name = "my-lambda"
23+
env = "dev"
24+
codedeploy_service_role_arn = module.acs.power_builder_role.arn
25+
lambda_src_dir = "./src"
26+
handler = "index.handler"
27+
runtime = "nodejs12.x"
28+
hosted_zone = module.acs.route53_zone
29+
https_certificate_arn = module.acs.certificate.arn
30+
vpc_id = module.acs.vpc.id
31+
public_subnet_ids = module.acs.public_subnet_ids
32+
private_subnet_ids = module.acs.private_subnet_ids
33+
role_permissions_boundary_arn = module.acs.role_permissions_boundary.arn
34+
codedeploy_test_listener_port = 4443
35+
36+
codedeploy_lifecycle_hooks = {
37+
BeforeAllowTraffic = aws_lambda_function.test_lambda.function_name
38+
AfterAllowTraffic = null
39+
}
40+
}
2041
```
42+
## Created Resources
43+
##### TODO fix this section (copy pasta from standard fargate)
44+
45+
* ECS Cluster
46+
* ECS Service
47+
* with security group
48+
* ECS Task Definition
49+
* with IAM role
50+
* CloudWatch Log Group
51+
* ALB
52+
* with security group
53+
* 2 Target Groups (for blue-green deployment)
54+
* CodeDeploy App
55+
* with IAM role
56+
* CodeDeploy Group
57+
* DNS A-Record
58+
* AutoScaling Target
59+
* AutoScaling Policies (one for stepping up and one for stepping down)
60+
* CloudWatch Metric Alarms (one for stepping up and one for stepping down)
2161

2262
## Requirements
2363
* Terraform version 0.12.21 or greater
@@ -26,11 +66,140 @@ This is done by:
2666
## Inputs
2767
| Name | Type | Description | Default |
2868
| --- | --- | --- | --- |
29-
| app_name | string | | |
30-
| codedeploy_service_role_arn | string | | |
31-
| lambda_src_dir | string | | |
32-
| hosted_zone | object | | |
69+
| app_name | string | application name |
70+
| env | string | application environment (e.g. dev, stg, prd) |
71+
| codedeploy_service_role_arn | string | ARN of the IAM Role for the CodeDeploy to use to initiate new deployments. (usually the PowerBuilder Role) |
72+
| lambda_src_dir | string | Directory that contains your lambda source code |
73+
| handler | string | Lambda event handler |
74+
| runtime | string | Lambda runtime |
75+
| environment_variables | map(string) | A map that defines environment variables for the Lambda function. |
76+
| hosted_zone | [object](#hosted_zone) | Hosted Zone object to redirect to ALB. (Can pass in the aws_hosted_zone object). A and AAAA records created in this hosted zone. |
77+
| https_certificate_arn | string | ARN of the HTTPS certificate of the hosted zone/domain. |
78+
| codedeploy_lifecycle_hooks | [object](#codedeploy_lifecycle_hooks) | Define Lambda Functions for CodeDeploy lifecycle event hooks. Or set this variable to null to not have any lifecycle hooks invoked. Defaults to null | null
79+
| codedeploy_test_listener_port | number | The port for a codedeploy test listener. If provided CodeDeploy will use this port for test traffic on the new replacement set during the blue-green deployment process before shifting production traffic to the replacement set. Defaults to null | null
80+
| vpc_id | string | VPC ID to deploy ECS fargate service. |
81+
| public_subnet_ids | list(string) | List of subnet IDs for the ALB. |
82+
| private_subnet_ids | list(string) | List of subnet IDs for the Lambda service. |
83+
| tags | map(string) | A map of AWS Tags to attach to each resource created | {}
84+
| role_permissions_boundary_arn | string | IAM Role Permissions Boundary ARN |
85+
| log_retention_in_days | number | CloudWatch log group retention in days. Defaults to 7. | 7
86+
| lambda_policies | list(string) | List of IAM Policy ARNs to attach to the lambda role. | []
87+
| security_groups | list(string) | List of extra security group IDs to attach to the lambda. | []
88+
89+
#### codedeploy_lifecycle_hooks
90+
91+
This variable is used when generating the [appspec.json](#appspec) file. This will define what Lambda Functions to invoke
92+
at specific [lifecycle hooks](https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html).
93+
Set this variable to `null` if you don't want to invoke any lambda functions. Set each hook to `null` if you don't need
94+
a specific lifecycle hook function.
95+
96+
* **`before_allow_traffic`** - lambda function name to run before public traffic points to new lambda version
97+
* **`after_allow_traffic`** - lambda function name to run after public traffic points to new lambda version
98+
99+
#### hosted_zone
100+
101+
You can pass in either the object from the AWS terraform provider for an AWS Hosted Zone, or just an object with the following attributes:
102+
* **`name`** - (Required) Name of the hosted zone
103+
* **`id`** - (Required) ID of the hosted zone
104+
105+
#### CloudWatch logs
106+
107+
This module will create a CloudWatch log group named `/aws/lambda/<app_name>-<env>`.
108+
109+
For instance with the [above example](#usage) the logs could be found in the CloudWatch log group: `aws/lambda/my-lambda-dev`.
33110

34111
## Outputs
112+
##### TODO fill out this section
113+
35114
| Name | Type | Description |
36115
| --- | --- | --- |
116+
117+
#### appspec
118+
##### TODO fix this section (copy pasta from standard fargate)
119+
120+
This module also creates a JSON file in the project directory: `appspec.json` used to initiate a CodeDeploy Deployment.
121+
122+
Here's an example appspec.json file this creates:
123+
```json
124+
{
125+
"Resources": [
126+
{
127+
"TargetService": {
128+
"Properties": {
129+
"LoadBalancerInfo": {
130+
"ContainerName": "example",
131+
"ContainerPort": 8000
132+
},
133+
"TaskDefinition": "arn:aws:ecs:us-west-2:123456789123:task-definition/example-api-def:2"
134+
},
135+
"Type": "AWS::ECS::SERVICE"
136+
}
137+
}
138+
],
139+
"version": 1
140+
}
141+
```
142+
And example with [lifecycle hooks](#codedeploy_lifecycle_hooks):
143+
```json
144+
{
145+
"Hooks": [
146+
{
147+
"BeforeInstall": null
148+
},
149+
{
150+
"AfterInstall": "AfterInstallHookFunctionName"
151+
},
152+
{
153+
"AfterAllowTestTraffic": "AfterAllowTestTrafficHookFunctionName"
154+
},
155+
{
156+
"BeforeAllowTraffic": null
157+
},
158+
{
159+
"AfterAllowTraffic": null
160+
}
161+
],
162+
"Resources": [
163+
{
164+
"TargetService": {
165+
"Properties": {
166+
"LoadBalancerInfo": {
167+
"ContainerName": "example",
168+
"ContainerPort": 8000
169+
},
170+
"TaskDefinition": "arn:aws:ecs:us-west-2:123456789123:task-definition/example-api-def:2"
171+
},
172+
"Type": "AWS::ECS::SERVICE"
173+
}
174+
}
175+
],
176+
"version": 1
177+
}
178+
```
179+
180+
## CodeDeploy Blue-Green Deployment
181+
##### TODO fix this section (copy pasta from standard fargate)
182+
183+
This module creates a blue-green deployment process with CodeDeploy. If a `codedeploy_test_listener_port` is provided
184+
this module will create an ALB listener that will allow public traffic from that port to the running lambda.
185+
186+
When a CodeDeploy deployment is initiated (either via a pipeline or manually) CodeDeploy will:
187+
1. call lambda function defined for `BeforeInstall` hook
188+
2. attempt to create a new set of tasks (called the replacement set) with the new task definition etc. in the unused ALB Target Group
189+
3. call lambda function defined for `AfterInstall` hook
190+
4. associate the test listener (if defined) to the new target group
191+
5. call lambda function defined for `AfterAllowTestTraffic` hook
192+
6. call lambda function defined for `BeforeAllowTraffic` hook
193+
7. associate the production listener to the new target group
194+
8. call lambda function defined for `AfterAllowTraffic` hook
195+
9. wait for the `codedeploy_termination_wait_time` in minutes before destroying the original task set (this is useful if you need to manually rollback)
196+
197+
At any step (except step #1) the deployment can rollback (either manually or by the lambda functions in the lifecycle hooks or if there was an error trying to actually deploy)
198+
199+
##### TODO add diagrams to explain the blue-green deployment process
200+
201+
## Note
202+
203+
If you require additional variables please create an [issue](https://github.com/byu-oit/terraform-aws-lambda-api/issues)
204+
and/or a [pull request](https://github.com/byu-oit/terraform-aws-lambda-api/pulls) to add the variable and reach
205+
out to the Terraform Working Group on slack (`#terraform` channel).

main.tf

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ data "archive_file" "cleanup_lambda_zip" {
225225
type = "zip"
226226
}
227227

228+
# TODO: the SG fails to destroy because the lambda's ENI is still using it.
228229
resource "aws_security_group" "lambda_sg" {
229230
name = "${local.long_name}-lambda-sg"
230231
description = "Controls access to the Lambda"
@@ -261,12 +262,6 @@ resource "aws_lambda_function" "api_lambda" {
261262
subnet_ids = var.private_subnet_ids
262263
security_group_ids = concat([aws_security_group.lambda_sg.id], var.security_groups)
263264
}
264-
265-
# environment {
266-
# variables = {
267-
# netid = "jvisker"
268-
# }
269-
# }
270265
}
271266

272267
resource "aws_lambda_alias" "live" {

0 commit comments

Comments
 (0)