From ca0948d96cac4f21a97a1d4d5243149580640641 Mon Sep 17 00:00:00 2001 From: Julen Dixneuf Date: Fri, 12 Apr 2024 15:09:51 +0200 Subject: [PATCH 1/5] docs: present the official AWS alternative --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ab84e3a..e2b42c8 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,22 @@ It uses a _lambda_ function and a few _cronjobs_ to trigger a _start_ or _stop_ It supports : - **AutoscalingGroups**: it suspends the ASG and terminates its instances. At the start, it resumes the ASG, which launches new instances by itself. -- RDS: support simple RDS DB instance. Run the function stop and start on them. -- ~~EC2 instances~~: maybe +- **EKS node groups**: if a node group is tagged, it will use the ASG handler for its underlying ASG. +- **RDS**: Run the function stop and start on them. +- **EC2 instances**: terminate instances. ⚠️ It does not start them back, as it is not stopped but terminated. Use with caution. The lambda function is _idempotent_, so you can launch it on an already stopped/started resource without any risks! It simplifies your job when planning with crons. ![aws_schema](./docs/assets/aws_schema.png) +### Why not use AWS Instance Scheduler instead? + +[AWS Instance Scheduler](https://github.com/aws-solutions/instance-scheduler-on-aws/tree/main) is the official AWS solution for this problem. It is a more complete solution, using a controlle approach: a lambda regularly checks the current time and decides to start or stop resources. It is therefore more resilient. + +However it is also more complex and needs to be setup with CloudFormation. + +A good rule of thumb to decide: if you have a few accounts and want to keep it simple, use this Terraform module. If you manage a multi-account cloud organization, check for the more complete and robust _Instance Scheduler_. + ### About cronjobs If you don't know much about crons, check . From c9865f60ec2a5d31aa5d94d82c5a82c9d781689e Mon Sep 17 00:00:00 2001 From: Julen Dixneuf Date: Fri, 12 Apr 2024 16:56:06 +0200 Subject: [PATCH 2/5] fix: set a higher default timeout --- README.md | 3 +++ variables.tf | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e2b42c8..72a214a 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,9 @@ module "aws_start_stop_scheduler" { tag_value = "staging", } ] + + # to adjust if you have a lot of resources to manage + # lamda_timeout = 600 } ``` diff --git a/variables.tf b/variables.tf index 10382cb..08ad91b 100644 --- a/variables.tf +++ b/variables.tf @@ -25,7 +25,7 @@ variable "tags" { } variable "lambda_timeout" { - default = 10 + default = 120 description = "Amount of time your Lambda Function has to run in seconds." type = number From c8e0966b57a23fad680584d9bf7b979d5e5d511f Mon Sep 17 00:00:00 2001 From: Julen Dixneuf Date: Fri, 12 Apr 2024 17:02:40 +0200 Subject: [PATCH 3/5] docs: explain how to use with Karpenter --- README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/README.md b/README.md index 72a214a..e44c1e5 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,37 @@ module "aws_start_stop_scheduler" { You have a full working example in [examples/custom_role](./examples/custom_role). +### Scale down an EKS cluster with Karpenter + +If you are using Karpenter on its own node group, which then schedules the pods on EC2 instances, you should + +1. First scale down the node group with Karpenter, to prevent it from scaling up new instances. +2. Then stop the EC2 instances. + +When you scale up the node group, Karpenter will schedule the pods on the new instances. It will also cleanup _ghost_ Kubernetes nodes from the API server. + +Here an example of how to do it : + +```hcl +schedules = [ + { + name = "weekday_asg_working_hours", + start = "0 6 ? * MON-FRI *", + stop = "0 19 ? * MON-FRI *", # 19:00 + tag_key = "scheduler", + tag_value = "karpenter_node_group" # EKS node group hosting karpenter is tagged with this + }, + { + name = "weekday_ec2_karpenter_working_hours", + start = "", # do not scale up + stop = "5 19 ? * MON-FRI *", # 19:05, 5 min after the ASG + tag_key = "scheduler", + tag_value = "ec2_karpenter" # EC2 instances launched by Karpenter are tagged with this + }, +] +``` + + ## Contributing Refer to the [contribution guidelines](./CONTRIBUTING.md) for From 4dabd6156dee961dee32838f02d5834ea5ad4f12 Mon Sep 17 00:00:00 2001 From: Julen Dixneuf Date: Fri, 12 Apr 2024 17:05:55 +0200 Subject: [PATCH 4/5] docs: tips for databases --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index e44c1e5..0286995 100644 --- a/README.md +++ b/README.md @@ -203,6 +203,28 @@ schedules = [ ] ``` +### Gracefully handle databases shutdown for applications + +To avoid any issues with application lock in databases (for example migrations), you should shutdown databases after the application has been stopped. For this you may use two different schedules : + +```hcl + schedules = [ + { + name = "weekday_asg_working_hours", + start = "0 6 ? * MON-FRI *", + stop = "0 19 ? * MON-FRI *", # 30 min before the RDS + tag_key = "scheduler", + tag_value = "asg" + }, + { + name = "weekday_rds_working_hours", + start = "30 5 ? * MON-FRI *", + stop = "30 19 ? * MON-FRI *", + tag_key = "scheduler", + tag_value = "rds" + }, + ] +``` ## Contributing From 027f7cb3138dcb0293682bd38489b6b779e0e931 Mon Sep 17 00:00:00 2001 From: Julen Dixneuf Date: Fri, 12 Apr 2024 17:08:01 +0200 Subject: [PATCH 5/5] docs: run terraform-docs --- README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0286995..405d00f 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,6 @@ If you don't know much about crons, check . :alarm-clock: All the cronjobs expressions are in UTC time ! Check your current timezone and do the maths. -## Compatibility - -This module is meant for use with Terraform >= 0.13 and `aws` provider >= 2. - ## Usage This module can be installed using Padok's registry. @@ -119,8 +115,8 @@ aws lambda invoke --function-name --payload '{"actio | Name | Version | |------|---------| -| [archive](#provider\_archive) | 2.3.0 | -| [aws](#provider\_aws) | 4.59.0 | +| [archive](#provider\_archive) | ~> 2.0 | +| [aws](#provider\_aws) | ~> 4.0 | ## Inputs @@ -133,7 +129,7 @@ aws lambda invoke --function-name --payload '{"actio | [custom\_iam\_lambda\_role](#input\_custom\_iam\_lambda\_role) | Use a custom role used for the lambda. Useful if you cannot create IAM ressource directly with your AWS profile, or to share a role between several resources. | `bool` | `false` | no | | [custom\_iam\_lambda\_role\_arn](#input\_custom\_iam\_lambda\_role\_arn) | Custom role arn used for the lambda. Used only if custom\_iam\_lambda\_role is set to true. | `string` | `null` | no | | [ec2\_schedule](#input\_ec2\_schedule) | Run the scheduler on EC2 instances. (only allows downscaling) | `bool` | `false` | no | -| [lambda\_timeout](#input\_lambda\_timeout) | Amount of time your Lambda Function has to run in seconds. | `number` | `10` | no | +| [lambda\_timeout](#input\_lambda\_timeout) | Amount of time your Lambda Function has to run in seconds. | `number` | `120` | no | | [rds\_schedule](#input\_rds\_schedule) | Run the scheduler on RDS. | `bool` | `true` | no | | [tags](#input\_tags) | Custom Resource tags | `map(string)` | `{}` | no |