diff --git a/.gitignore b/.gitignore index 4c0af394..cdc5b18c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .DS_Store .terraform.lock.hcl .terraform +*.out diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index de70ecd6..8226665d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: rev: v4.1.0 hooks: # See https://pre-commit.com/hooks.html for more hooks - - id: check-added-large-files + #- id: check-added-large-files - id: check-byte-order-marker - id: check-case-conflict - id: check-executables-have-shebangs diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..85d8fff7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,43 @@ +# Change Log + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + + +## [0.0.4] + +- parameterized deployment yaml manifests with cookiecutter +- refactored VPC and EKS modules based on the current latest version of terraform-aws-modules modules +- upgraded AWS RDS Terraform module to v4 +- added AWS certficates in us-east-1 and the aws region specified in environments/global.hcl +- added new module for Cloudfront distribution and DNS record for 'cdn' subdomain +- added new optional module for EC2 Bastion and DNS record for subdomain +- added version constraint parameters to cookiecutter for all terraform-aws-modules +- added mock outputs to terragrunt scripts to facilitate `run-all` init and validate operations in environments +- added this change log +- resolved deprecation warnings in all modules +- restructured terraform folders +- fixed a bug that was causing multiple SSL/TLS certificates to be created in both us-east-1 as well as the environment region +- added the text 'openedx_devops' to the descriptions of all security groups, IAM roles, and IAM policies resources that are explicitly created by this repository + + +## [0.0.3] - 2022-03-20 + +- added Cookiecutter parameters for environment_subdomain, ci_build_open_edx_version, ci_build_tutor_version, all teraform version constraints +- split environment_name and environment_subdomain +- added Cookiecutter post hook to process selection of EKS Load Balancer configuration +- added scripts to make, test, lint +- more sensible defaults in cookiecutter.json +- expanded README.md documentation +- added git pre-commit +- added AUTHORS.md + +## [0.0.2] - 2022-03-11 + +- Additional documentation + +## [0.0.1] - 2022-03-10 + +Initial release diff --git a/README.rst b/README.rst index 336ede24..18dff19c 100644 --- a/README.rst +++ b/README.rst @@ -47,9 +47,9 @@ Cookiecutter Tutor Open edX Production Devops Tools This repository contains a `Cookiecutter `_ to create a new repository that includes Terraform code for managing your AWS infrastructure, and Github Actions workflows for building and deploying your Open edX applications. Your new repository will deploy a `Tutor `_ Kubernetes-managed production installation of Open edX that will scale automatically, reliably supporting anywhere from a few hundred to as many as several hundred thousand learners. +It provides both `AWS Fargate `_ as well as more traditional EC2 instance computing node options for the EKS Kubernetes cluster. The CI workflows generated by this Cookiecutter create a Tutor build based on the current latest version of Open edX ({{ cookiecutter.ci_build_open_edx_version }}) along with a custom Open edX theme and Open edX plugin, and one sample optional Xblock; all of which can be modified later on. - The Terraform scripts in your new repo will provide a 1-click means of creating / updating / destroying the following for each environment: - LMS at https://courses.yourschool.edu @@ -90,18 +90,39 @@ First, get Cookiecutter. Trust me, it's awesome: $ pip install "cookiecutter>=1.7.0" -Now run it against this repo: +Now run it against this repo, using the following example usage pattern: .. code-block:: shell - $ cookiecutter https://github.com/lpm0073/cookiecutter-openedx-devops - -You'll be prompted for some values. Provide them, then a complete git repository will be created for you, with Github Actions workflows to automate the build and deployment of your Tutor Open edX platform, and Terraform scripts to automate the build of your AWS backend. + GITHUB_REPO="gh:lpm0073/cookiecutter-openedx-devops" + GITHUB_BRANCH="main" + OUTPUT_FOLDER="./" + + cookiecutter --checkout $GITHUB_BRANCH \ + --output-dir $OUTPUT_FOLDER \ + --overwrite-if-exists \ + --no-input \ + $GITHUB_REPO \ + global_platform_name=prod \ + global_platform_region=usa \ + global_aws_region=us-east-1 \ + global_account_id=012345678912 \ + global_root_domain=schoolofrock.edu \ + global_aws_route53_hosted_zone_id=Z123456789ABCDEFGHIJK \ + environment_name=live \ + environment_subdomain=courses \ + kubernetes_cluster_compute_type=EC2 \ + kubernetes_cluster_load_balancer_type=ALB + + +Alternatively, you can run Cookiecutter without providing any prompts, which will result in it generating a questionnaire that includes all of the 75 or so input parameters. You'll be prompted for some values. Provide them, then a complete git repository will be created for you, with Github Actions workflows to automate the build and deployment of your Tutor Open edX platform, and Terraform scripts to automate the build of your AWS backend. Answer the prompts with your own desired options. For example: .. code-block:: shell + $ cookiecutter https://github.com/lpm0073/cookiecutter-openedx-devops + Cloning into 'cookiecutter-openedx-devops'... remote: Counting objects: 550, done. remote: Compressing objects: 100% (310/310), done. @@ -114,50 +135,7 @@ Answer the prompts with your own desired options. For example: global_platform_description [Your School]: global_platform_region [virginia]: global_root_domain [yourschool.edu]: - global_aws_route53_hosted_zone_id [For your root domain. Values look like this: Z0232691KVI7Y7U23HBD]: - global_aws_region [us-east-1]: - global_account_id [123456789012]: - global_ec2_ssh_key_name [any-valid-pem-key-file-name]: - prod_environment [courses]: - ci_build_tutor_version [v13.1.5]: - ci_build_theme_repository [lpm0073/edx-theme-example]: - ci_build_theme_ref [main]: - ci_build_plugin_repository [lpm0073/openedx-plugin-example]: - ci_build_plugin_ref [main]: - ci_build_xblock_org [openedx]: - ci_build_xblock_repository [edx-ora2]: - ci_build_xblock_ref [master]: - ci_deploy_OPENEDX_COMMON_VERSION [open-release/{{ cookiecutter.ci_build_open_edx_version }}]: - mongodb_master_username [root]: - mongodb_db_port [27017]: - mongodb_deletion_protection [False]: - mongodb_engine [docdb]: - mongodb_engine_version [3.6.0]: - mongodb_retention_period [7]: - mongodb_preferred_maintenance_window []: - mongodb_preferred_backup_window [07:00-09:00]: - mongodb_auto_minor_version_upgrade [True]: - mysql_username [root]: - mysql_port [3306]: - mysql_engine [mysql]: - mysql_family [mysql5.7]: - mysql_major_engine_version [5.7]: - mysql_engine_version [5.7.33]: - mysql_allocated_storage [10]: - mysql_create_random_password [true]: - mysql_iam_database_authentication_enabled [False]: - mysql_maintenance_window [Sun:00:00-Sun:03:00]: - mysql_backup_window [03:00-06:00]: - mysql_backup_retention_period [7]: - mysql_deletion_protection [False]: - mysql_skip_final_snapshot [True]: - redis_engine_version [6.x]: - redis_number_cache_clusters [1]: - redis_port [6379]: - redis_family [redis6.x]: - ci_deploy_EMAIL_HOST [email-smtp.us-east-1.amazonaws.com]: - ci_deploy_EMAIL_PORT [587]: - ci_deploy_EMAIL_USE_TLS [True]: + # lots more questions ..... Enter the project and take a look around: @@ -258,7 +236,7 @@ We also recommend that you install `k9s `_, a popular tool f # ------------------------------------- # to manage an individual resource # ------------------------------------- - cd ./terraform/environments/prod/mongodb + cd ./terraform/environments/{{ cookiecutter.environment_name }}/mongodb terragrunt init terragrunt plan terragrunt apply @@ -269,11 +247,11 @@ We also recommend that you install `k9s `_, a popular tool f # ------------------------------------- # 1. create the VPC - cd ./terraform/environments/prod/vpc + cd ./terraform/environments/{{ cookiecutter.environment_name }}/vpc terragrunt apply # 2. create the Elastic Kubernetes Cluster - cd ../eks + cd ../kubernetes terragrunt apply # 3. create everthing else @@ -335,18 +313,18 @@ The Terraform scripts in your new repository will allow you to automatically cre - **Compute Cluster**. uses either `AWS EC2 `_ behind a Classic Load Balancer (the default) or AWS' serverless compute cluster, `Fargate `_ behind an Application Load Balancer. - **Kubernetes**. Uses `AWS Elastic Kubernetes Service `_ to implement a Kubernetes cluster onto which all applications and scheduled jobs are deployed as pods. -- **MySQL**. uses `AWS RDS `_ for all MySQL data, accessible inside the vpc as mysql.courses.yourschool.edu:3306. Instance size settings are located in the `environment configuration file `_, and other common configuration settings `are located here `_. Passwords are stored in `Kubernetes Secrets `_ accessible from the EKS cluster. -- **MongoDB**. uses `AWS DocumentDB `_ for all MongoDB data, accessible insid the vpc as mongodb.master.courses.yourschool.edu:27017 and mongodb.reader.courses.yourschool.edu. Instance size settings are located in the `environment configuration file `_, and other common configuration settings `are located here `_. Passwords are stored in `Kubernetes Secrets `_ accessible from the EKS cluster. -- **Redis**. uses `AWS ElastiCache `_ for all Django application caches, accessible inside the vpc as cache.courses.yourschool.edu. Instance size settings are located in the `environment configuration file `_. This is necessary in order to make the Open edX application layer completely ephemeral. Most importantly, user's login session tokens are persisted in Redis and so these need to be accessible to all app containers from a single Redis cache. Common configuration settings `are located here `_. Passwords are stored in `Kubernetes Secrets `_ accessible from the EKS cluster. -- **Container Registry**. uses this `automated Github Actions workflow <.github/workflows/tutor_build_image.yml>`_ to build your `tutor Open edX container `_ and then register it in `Amazon Elastic Container Registry (Amazon ECR) `_. Uses this `automated Github Actions workflow <.github/workflows/tutor_deploy_prod.yml>`_ to deploy your container to `AWS Amazon Elastic Kubernetes Service (EKS) `_. EKS worker instance size settings are located in the `environment configuration file `_. Note that tutor provides out-of-the-box support for Kubernetes. Terraform leverages Elastic Kubernetes Service to create a Kubernetes cluster onto which all services are deployed. Common configuration settings `are located here `_ -- **User Data**. uses `AWS S3 `_ for storage of user data. This installation makes use of a `Tutor plugin to offload object storage `_ from the Ubuntu file system to AWS S3. It creates a public read-only bucket named of the form courses-yourschool-virginia-storage, with write access provided to edxapp so that app-generated static content like user profile images, xblock-generated file content, application badges, e-commerce pdf receipts, instructor grades downloads and so on will be saved to this bucket. This is not only a necessary step for making your application layer ephemeral but it also facilitates the implementation of a CDN (which Terraform implements for you). Terraform additionally implements a completely separate, more secure S3 bucket for archiving your daily data backups of MySQL and MongoDB. Common configuration settings `are located here `_ -- **CDN**. uses `AWS Cloudfront `_ as a CDN, publicly acccessible as https://cdn.courses.yourschool.edu. Terraform creates Cloudfront distributions for each of your enviornments. These are linked to the respective public-facing S3 Bucket for each environment, and the requisite SSL/TLS ACM-issued certificate is linked. Terraform also automatically creates all Route53 DNS records of form cdn.courses.yourschool.edu. Common configuration settings `are located here `_ -- **Password & Secrets Management** uses `Kubernetes Secrets `_ in the EKS cluster. Open edX software relies on many passwords and keys, collectively referred to in this documentation simply as, "*secrets*". For all back services, including all Open edX applications, system account and root passwords are randomly and strongluy generated during automated deployment and then archived in EKS' secrets repository. This methodology facilitates routine updates to all of your passwords and other secrets, which is good practice these days. Common configuration settings `are located here `_ -- **SSL Certs**. Uses `AWS Certificate Manager `_ and LetsEncrypt. Terraform creates all SSL/TLS certificates. It uses a combination of AWS Certificate Manager (ACM) as well as LetsEncrypt. Additionally, the ACM certificates are stored in two locations: your aws-region as well as in us-east-1 (as is required by AWS CloudFront). Common configuration settings `are located here `_ -- **DNS Management** uses `AWS Route53 `_ hosted zones for DNS management. Terraform expects to find your root domain already present in Route53 as a hosted zone. It will automatically create additional hosted zones, one per environment for production, dev, test and so on. It automatically adds NS records to your root domain hosted zone as necessary to link the zones together. Configuration data exists within several components but the highest-level settings `are located here `_ +- **MySQL**. uses `AWS RDS `_ for all MySQL data, accessible inside the vpc as mysql.courses.yourschool.edu:3306. Instance size settings are located in the `environment configuration file `_, and other common configuration settings `are located here `_. Passwords are stored in `Kubernetes Secrets `_ accessible from the EKS cluster. +- **MongoDB**. uses `AWS DocumentDB `_ for all MongoDB data, accessible insid the vpc as mongodb.master.courses.yourschool.edu:27017 and mongodb.reader.courses.yourschool.edu. Instance size settings are located in the `environment configuration file `_, and other common configuration settings `are located here `_. Passwords are stored in `Kubernetes Secrets `_ accessible from the EKS cluster. +- **Redis**. uses `AWS ElastiCache `_ for all Django application caches, accessible inside the vpc as cache.courses.yourschool.edu. Instance size settings are located in the `environment configuration file `_. This is necessary in order to make the Open edX application layer completely ephemeral. Most importantly, user's login session tokens are persisted in Redis and so these need to be accessible to all app containers from a single Redis cache. Common configuration settings `are located here `_. Passwords are stored in `Kubernetes Secrets `_ accessible from the EKS cluster. +- **Container Registry**. uses this `automated Github Actions workflow <.github/workflows/tutor_build_image.yml>`_ to build your `tutor Open edX container `_ and then register it in `Amazon Elastic Container Registry (Amazon ECR) `_. Uses this `automated Github Actions workflow <.github/workflows/tutor_deploy_prod.yml>`_ to deploy your container to `AWS Amazon Elastic Kubernetes Service (EKS) `_. EKS worker instance size settings are located in the `environment configuration file `_. Note that tutor provides out-of-the-box support for Kubernetes. Terraform leverages Elastic Kubernetes Service to create a Kubernetes cluster onto which all services are deployed. Common configuration settings `are located here `_ +- **User Data**. uses `AWS S3 `_ for storage of user data. This installation makes use of a `Tutor plugin to offload object storage `_ from the Ubuntu file system to AWS S3. It creates a public read-only bucket named of the form courses-yourschool-virginia-storage, with write access provided to edxapp so that app-generated static content like user profile images, xblock-generated file content, application badges, e-commerce pdf receipts, instructor grades downloads and so on will be saved to this bucket. This is not only a necessary step for making your application layer ephemeral but it also facilitates the implementation of a CDN (which Terraform implements for you). Terraform additionally implements a completely separate, more secure S3 bucket for archiving your daily data backups of MySQL and MongoDB. Common configuration settings `are located here `_ +- **CDN**. uses `AWS Cloudfront `_ as a CDN, publicly acccessible as https://cdn.courses.yourschool.edu. Terraform creates Cloudfront distributions for each of your enviornments. These are linked to the respective public-facing S3 Bucket for each environment, and the requisite SSL/TLS ACM-issued certificate is linked. Terraform also automatically creates all Route53 DNS records of form cdn.courses.yourschool.edu. Common configuration settings `are located here `_ +- **Password & Secrets Management** uses `Kubernetes Secrets `_ in the EKS cluster. Open edX software relies on many passwords and keys, collectively referred to in this documentation simply as, "*secrets*". For all back services, including all Open edX applications, system account and root passwords are randomly and strongluy generated during automated deployment and then archived in EKS' secrets repository. This methodology facilitates routine updates to all of your passwords and other secrets, which is good practice these days. Common configuration settings `are located here `_ +- **SSL Certs**. Uses `AWS Certificate Manager `_ and LetsEncrypt. Terraform creates all SSL/TLS certificates. It uses a combination of AWS Certificate Manager (ACM) as well as LetsEncrypt. Additionally, the ACM certificates are stored in two locations: your aws-region as well as in us-east-1 (as is required by AWS CloudFront). Common configuration settings `are located here `_ +- **DNS Management** uses `AWS Route53 `_ hosted zones for DNS management. Terraform expects to find your root domain already present in Route53 as a hosted zone. It will automatically create additional hosted zones, one per environment for production, dev, test and so on. It automatically adds NS records to your root domain hosted zone as necessary to link the zones together. Configuration data exists within several modules but the highest-level settings `are located here `_ - **System Access** uses `AWS Identity and Access Management (IAM) `_ to manage all system users and roles. Terraform will create several user accounts with custom roles, one or more per service. -- **Network Design**. uses `Amazon Virtual Private Cloud (Amazon VPC) `_ based on the AWS account number provided in the `global configuration file `_ to take a top-down approach to compartmentalize all cloud resources and to customize the operating enviroment for your Open edX resources. Terraform will create a new virtual private cloud into which all resource will be provisioned. It creates a sensible arrangment of private and public subnets, network security settings and security groups. See additional VPC documentation `here `_ -- **Proxy Access to Backend Services**. uses an `Amazon EC2 `_ t2.micro Ubuntu instance publicly accessible via ssh as bastion.courses.yourschool.edu:22 using the ssh key specified in the `global configuration file `_. For security as well as performance reasons all backend services like MySQL, Mongo, Redis and the Kubernetes cluster are deployed into their own private subnets, meaning that none of these are publicly accessible. See additional Bastion documentation `here `_. Terraform creates a t2.micro EC2 instance to which you can connect via ssh. In turn you can connect to services like MySQL via the bastion. Common configuration settings `are located here `_. Note that if you are cost conscious then you could alternatively use `AWS Cloud9 `_ to gain access to all backend services. +- **Network Design**. uses `Amazon Virtual Private Cloud (Amazon VPC) `_ based on the AWS account number provided in the `global configuration file `_ to take a top-down approach to compartmentalize all cloud resources and to customize the operating enviroment for your Open edX resources. Terraform will create a new virtual private cloud into which all resource will be provisioned. It creates a sensible arrangment of private and public subnets, network security settings and security groups. See additional VPC documentation `here `_ +- **Proxy Access to Backend Services**. uses an `Amazon EC2 `_ t2.micro Ubuntu instance publicly accessible via ssh as bastion.courses.yourschool.edu:22 using the ssh key specified in the `global configuration file `_. For security as well as performance reasons all backend services like MySQL, Mongo, Redis and the Kubernetes cluster are deployed into their own private subnets, meaning that none of these are publicly accessible. See additional Bastion documentation `here `_. Terraform creates a t2.micro EC2 instance to which you can connect via ssh. In turn you can connect to services like MySQL via the bastion. Common configuration settings `are located here `_. Note that if you are cost conscious then you could alternatively use `AWS Cloud9 `_ to gain access to all backend services. FAQ --- @@ -385,7 +363,7 @@ Behind the scenes Kubernetes (EKS in our case) uses an EC2 Elastic Load Balancer Why Use Terraform? ~~~~~~~~~~~~~~~~~~ -`Terraform `_ allows you to manage the entire lifecycle of your AWS cloud infrastructure using `infrastructure as code (IAC) `_. That means declaring infrastructure components in configuration files that are then used by Terraform to provision, adjust and tear down your AWS cloud infrastructure. There are tangential benefits to using IAC. +`Terraform `_ allows you to manage the entire lifecycle of your AWS cloud infrastructure using `infrastructure as code (IAC) `_. That means declaring infrastructure resources in configuration files that are then used by Terraform to provision, adjust and tear down your AWS cloud infrastructure. There are tangential benefits to using IAC. 1. **Maintain all of your backend configuration data in a single location**. This allows you to take a more holistic, top-down approach to planning and managing your backend resources, which leads to more reliable service for your users. 2. **Leverage git**. This is a big deal! Managing your backend as IAC means you can track individual changes to your configuration over time. More importantly, it means you can reverse backend configuration changes that didn't go as planned. @@ -430,8 +408,10 @@ Special thanks go out to several folks in the open source community who've alrea - to `RĂ©gis Behmo `_ for creating Tutor, where the real magic happens. Without Tutor you wouldn't be reading this right now. - to `Miguel Afonso `_, who architected the Kubernetes-based deployment of Open edX and wrote nearly all of the early versions of the CI and Terraform code. +- to `Anton Putra `_ for his great techical how-to articles on using ALB with EKS. - to `Harshet Jain `_ for publishing a `great article `_ on how to implement an AWS Elastic Kubernetes Fargate Cluster. - to the guys at `hastexo/tutor-contrib-s3 `_, who lead the effort to create a version of their AWS S3 plugin that works with this code base. +- to the guys at `U.S. General Services Administration `_ for open-sourcing their `ALB Ingress Controller installer `_. - to the guys at `Cookiecutter Django `_ on which I relied heavily for coding examples for this project. - to `Querium Corp `_, who generously allowed me to open-source this repository. - to **UK Cabinet Office**, who created and still use the original version of this code base to manage their production Open edX environment. diff --git a/cookiecutter.json b/cookiecutter.json index e95a72a8..1556ae66 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -3,6 +3,7 @@ "github_repo_name": "openedx_devops", "environment_name": "prod", "environment_subdomain": "courses", + "environment_add_bastion": ["N", "Y"], "global_platform_name": "yourschool", "global_platform_description": "Your School", "global_platform_region": "usa_east", @@ -21,21 +22,23 @@ "ci_build_xblock_repository": "edx-ora2", "ci_build_xblock_ref": "master", "ci_deploy_OPENEDX_COMMON_VERSION": "open-release/{{ cookiecutter.ci_build_open_edx_version }}", + "ci_deploy_hastexo_tutor_contrib_s3_version": "v0.2.0", "ci_deploy_EMAIL_HOST": "email-smtp.{{ cookiecutter.global_aws_region|lower|replace(' ', '-') }}.amazonaws.com", "ci_deploy_EMAIL_PORT": 587, - "ci_deploy_EMAIL_USE_TLS": true, - "eks_cluster_version": "1.21", - "eks_cluster_compute_type": ["CLB_EC2"], - "eks_cluster_alb_ingress_controller_version": "v2.4.1", + "ci_deploy_EMAIL_USE_TLS": "true", + "kubernetes_cluster_version": "1.21", + "kubernetes_cluster_compute_type": ["EC2", "Fargate"], + "kubernetes_cluster_load_balancer_type": ["ALB", "CLB"], + "kubernetes_cluster_ingress_controller_version": "v2.4.1", "mongodb_master_username": "root", "mongodb_db_port": 27017, - "mongodb_deletion_protection": false, + "mongodb_deletion_protection": "false", "mongodb_engine": "docdb", "mongodb_engine_version": "3.6.0", "mongodb_retention_period": 7, "mongodb_preferred_maintenance_window": "", "mongodb_preferred_backup_window": "07:00-09:00", - "mongodb_auto_minor_version_upgrade": true, + "mongodb_auto_minor_version_upgrade": "true", "mysql_username": "root", "mysql_port": 3306, "mysql_engine": "mysql", @@ -44,18 +47,30 @@ "mysql_engine_version": "5.7.33", "mysql_allocated_storage": 10, "mysql_create_random_password": "true", - "mysql_iam_database_authentication_enabled": false, + "mysql_iam_database_authentication_enabled": "false", "mysql_maintenance_window": "Sun:00:00-Sun:03:00", "mysql_backup_window": "03:00-06:00", "mysql_backup_retention_period": 7, - "mysql_deletion_protection": false, - "mysql_skip_final_snapshot": true, + "mysql_deletion_protection": "false", + "mysql_skip_final_snapshot": "true", "redis_engine_version": "6.x", - "redis_number_cache_clusters": 1, + "redis_num_cache_clusters": 1, "redis_port": 6379, "redis_family": "redis6.x", "terraform_required_version": "~> 1.1", - "terraform_provider_kubernetes_version": "~> 2.8", + "terraform_aws_modules_acm": "~> 3.4", + "terraform_aws_modules_cloudfront": "~> 2.9", + "terraform_aws_modules_eks": "~> 18.15", + "terraform_aws_modules_iam": "~> 4.14", + "terraform_aws_modules_rds": "~> 4.2.0", + "terraform_aws_modules_s3": "~> 3.0", + "terraform_aws_modules_sg": "~> 4.9", + "terraform_aws_modules_vpc": "~> 3.13", + "terraform_helm_ingress_nginx": "~> 4", + "terraform_helm_cert_manager": "v1.7.1", + "terraform_helm_alb_controller_chart_version": "1.4.1", + "terraform_helm_aws_efs_csi_driver_version": "1.3.6", + "terraform_provider_kubernetes_version": "~> 2.9", "terraform_provider_hashicorp_aws_version": "~> 4.6", "terraform_provider_hashicorp_helm_version": "~> 2.4", "terraform_provider_hashicorp_local_version": "~> 2.2", diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 1ae9e832..9fec33a3 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -11,73 +11,18 @@ HINT = "\x1b[3;33m" SUCCESS = "\x1b[1;32m [SUCCESS]: " +def remove_bastion(): + module_dir_path = os.path.join("terraform", "modules", "ec2_bastion") + if os.path.exists(module_dir_path): + shutil.rmtree(module_dir_path) -def remove_eks_clb_ec2_files(): - component_dir_path = os.path.join("terraform", "components", "eks_clb_ec2") - if os.path.exists(component_dir_path): - shutil.rmtree(component_dir_path) - - terragrunt_dir_path = os.path.join("terraform", "environments", "{{ cookiecutter.environment_name }}", "eks_clb_ec2") - if os.path.exists(terragrunt_dir_path): - shutil.rmtree(terragrunt_dir_path) - - ci_dir_path = os.path.join("ci", "tutor-deploy", "environments", "{{ cookiecutter.environment_name }}", "k8s", "eks_clb_ec2") - if os.path.exists(ci_dir_path): - shutil.rmtree(ci_dir_path) - -def remove_eks_alb_ec2_files(): - component_dir_path = os.path.join("terraform", "components", "eks_alb_ec2") - if os.path.exists(component_dir_path): - shutil.rmtree(component_dir_path) - - terragrunt_dir_path = os.path.join("terraform", "environments", "{{ cookiecutter.environment_name }}", "eks_alb_ec2") - if os.path.exists(terragrunt_dir_path): - shutil.rmtree(terragrunt_dir_path) - - ci_dir_path = os.path.join("ci", "tutor-deploy", "environments", "{{ cookiecutter.environment_name }}", "k8s", "eks_alb_ec2") - if os.path.exists(ci_dir_path): - shutil.rmtree(ci_dir_path) - -def remove_eks_abl_fargate_files(): - component_dir_path = os.path.join("terraform", "components", "eks_alb_fargate") - if os.path.exists(component_dir_path): - shutil.rmtree(component_dir_path) - - terragrunt_dir_path = os.path.join("terraform", "environments", "{{ cookiecutter.environment_name }}", "eks_alb_fargate") + terragrunt_dir_path = os.path.join("terraform", "environments", "{{ cookiecutter.environment_name }}", "ec2_bastion") if os.path.exists(terragrunt_dir_path): shutil.rmtree(terragrunt_dir_path) - ci_dir_path = os.path.join("ci", "tutor-deploy", "environments", "{{ cookiecutter.environment_name }}", "k8s", "eks_alb_fargate") - if os.path.exists(ci_dir_path): - shutil.rmtree(ci_dir_path) - -# move kubernetes manifests into the k8s folder and remove the original source folder. -def move_manifests(folder = ""): - source = os.path.join("ci", "tutor-deploy", "environments", "{{ cookiecutter.environment_name }}", "k8s", folder) - destination = os.path.join("ci", "tutor-deploy", "environments", "{{ cookiecutter.environment_name }}", "k8s") - src_files = os.listdir(source) - for file_name in src_files: - full_file_name = os.path.join(source, file_name) - if os.path.isfile(full_file_name): - shutil.copy(full_file_name, destination) - shutil.rmtree(source) - def main(): - - if "{{ cookiecutter.eks_cluster_compute_type }}" == "CLB_EC2": - remove_eks_abl_fargate_files() - remove_eks_alb_ec2_files() - move_manifests("eks_clb_ec2") - - if "{{ cookiecutter.eks_cluster_compute_type }}" == "ALB_EC2": - remove_eks_abl_fargate_files() - remove_eks_clb_ec2_files() - move_manifests("eks_alb_ec2") - - if "{{ cookiecutter.eks_cluster_compute_type }}" == "ALB_Fargate": - remove_eks_clb_ec2_files() - remove_eks_alb_ec2_files() - move_manifests("eks_alb_fargate") + if "{{ cookiecutter.environment_add_bastion }}".upper() != "Y": + remove_bastion() print(SUCCESS + "Your Open edX devops repo has been initialized." + TERMINATOR) diff --git a/tests/test.sh b/tests/test.sh index 8660c902..4e1a0410 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -10,7 +10,7 @@ #------------------------------------------------------------------------------ GITHUB_REPO="gh:lpm0073/cookiecutter-openedx-devops" -GITHUB_BRANCH="eks-fargate" +GITHUB_BRANCH="eks_alb" OUTPUT_FOLDER="/Users/mcdaniel/cookiecutter/" cookiecutter --checkout $GITHUB_BRANCH \ @@ -18,11 +18,15 @@ cookiecutter --checkout $GITHUB_BRANCH \ --overwrite-if-exists \ --no-input \ $GITHUB_REPO \ - global_platform_name=sandbox \ - global_platform_region=ohio \ + global_platform_name=stepwisemath \ + global_platform_region=mexico \ global_aws_region=us-east-2 \ global_account_id=320713933456 \ global_root_domain=stepwisemath.ai \ - global_aws_route53_hosted_zone_id=Z049210026A5G6XHV84CF \ - environment_name=fargate \ - environment_subdomain=fargate + global_aws_route53_hosted_zone_id=Z0232691KVI7Y7U23HBD \ + global_ec2_ssh_key_name=stepwisemath-ohio \ + environment_name=prod \ + environment_add_bastion=N \ + environment_subdomain=web \ + kubernetes_cluster_compute_type=Fargate \ + kubernetes_cluster_load_balancer_type=ALB diff --git a/{{cookiecutter.github_repo_name}}/.github/workflows/tutor_deploy_prod.yml b/{{cookiecutter.github_repo_name}}/.github/workflows/tutor_deploy_{{cookiecutter.environment_name}}.yml similarity index 95% rename from {{cookiecutter.github_repo_name}}/.github/workflows/tutor_deploy_prod.yml rename to {{cookiecutter.github_repo_name}}/.github/workflows/tutor_deploy_{{cookiecutter.environment_name}}.yml index 476fca4d..dc0fad64 100644 --- a/{{cookiecutter.github_repo_name}}/.github/workflows/tutor_deploy_prod.yml +++ b/{{cookiecutter.github_repo_name}}/.github/workflows/tutor_deploy_{{cookiecutter.environment_name}}.yml @@ -16,7 +16,7 @@ # 7. use Tutor to startup the edxapp platform # 8. initialize Kubernetes, and then let it take over #------------------------------------------------------------------------------ -name: Tutor Deploy Prod +name: Tutor Deploy {{ cookiecutter.environment_name }} on: [workflow_dispatch] @@ -25,8 +25,8 @@ jobs: runs-on: ubuntu-20.04 env: KUBECONFIG: /home/runner/.kube/config - ENVIRONMENT_ID: prod - NAMESPACE: {{ cookiecutter.environment_name }}-{{ cookiecutter.global_platform_name }}-{{ cookiecutter.global_platform_region }} + ENVIRONMENT_ID: {{ cookiecutter.environment_name }} + NAMESPACE: openedx TUTOR_VERSION: {{ cookiecutter.ci_build_tutor_version }} OPENEDX_COMMON_VERSION: {{ cookiecutter.ci_deploy_OPENEDX_COMMON_VERSION }} @@ -44,7 +44,7 @@ jobs: aws-region: {{ cookiecutter.global_aws_region }} - name: Get Kube config - run: aws eks --region {{ cookiecutter.global_aws_region }} update-kubeconfig --name {{ cookiecutter.environment_name }}-{{ cookiecutter.global_platform_name }}-{{ cookiecutter.global_platform_region }} --alias eks-prod + run: aws eks --region {{ cookiecutter.global_aws_region }} update-kubeconfig --name {{ cookiecutter.environment_name }}-{{ cookiecutter.global_platform_name }}-{{ cookiecutter.global_platform_region }} --alias eks-{{ cookiecutter.environment_name }} - name: Install kubectl uses: azure/setup-kubectl@v1 @@ -67,13 +67,13 @@ jobs: run: |- echo "OPENEDX_COMMON_VERSION=$OPENEDX_COMMON_VERSION" >> $GITHUB_ENV - # see: https://github.com/{{ cookiecutter.github_account_name }}/terraform-openedx/tree/main/ci/tutor-deploy/environments/prod/jwt + # see: https://github.com/{{ cookiecutter.github_account_name }}/terraform-openedx/tree/main/ci/tutor-deploy/environments/{{ cookiecutter.environment_name }}/jwt - name: Fetch JWT token run: |- ### Fetch secrets from Kubernetes into Environment kubectl get secret jwt -n $NAMESPACE -o json | jq '.data| map_values(@base64d)' | jq -r 'keys[] as $k | "\(.[$k])"' > jwt_private_key - # see: https://github.com/{{ cookiecutter.github_account_name }}/terraform-openedx/tree/main/ci/tutor-deploy/environments/prod/rds + # see: https://github.com/{{ cookiecutter.github_account_name }}/terraform-openedx/tree/main/ci/tutor-deploy/environments/{{ cookiecutter.environment_name }}/rds - name: MySQL run: |- echo "TUTOR_RUN_MYSQL=false" >> $GITHUB_ENV @@ -85,7 +85,7 @@ jobs: echo "TUTOR_RUN_MONGODB=false" >> $GITHUB_ENV kubectl get secret mongodb-admin -n $NAMESPACE -o json | jq '.data | map_values(@base64d)' | jq -r 'keys[] as $k | "TUTOR_\($k|ascii_upcase)=\(.[$k])"' >> $GITHUB_ENV - # see: https://github.com/{{ cookiecutter.github_account_name }}/terraform-openedx/tree/main/ci/tutor-deploy/environments/prod/redis + # see: https://github.com/{{ cookiecutter.github_account_name }}/terraform-openedx/tree/main/ci/tutor-deploy/environments/{{ cookiecutter.environment_name }}/redis - name: Redis run: |- echo "TUTOR_RUN_REDIS=false" >> $GITHUB_ENV @@ -116,7 +116,7 @@ jobs: cat ci/tutor-deploy/environments/$ENVIRONMENT_ID/config.yml >> $GITHUB_ENV # note that values like $LMS_HOSTNAME come from this repo - # in /ci/tutor-deploy/environments/prod/config.yml + # in /ci/tutor-deploy/environments/{{ cookiecutter.environment_name }}/config.yml - name: Load additional environment specific settings (computed) run: |- # We don't want to run these services as we are using the Kubernetes ingress instead. @@ -129,7 +129,7 @@ jobs: echo "TUTOR_RUN_NGINX=false" >> $GITHUB_ENV # note that the Kubernetes additional config data is locally - # stored in ci/tutor-deploy/environments/prod/k8s/ + # stored in ci/tutor-deploy/environments/{{ cookiecutter.environment_name }}/k8s/ - name: Create Kubernetes add-on resources run: |- # Create kubernetes ingress and other environment resources @@ -192,7 +192,7 @@ jobs: cat $TUTOR_ROOT/config.yml # in this step we're combining our custom configuration data - # from ci/tutor-deploy/environments/prod/settings_merge.json with the default + # from ci/tutor-deploy/environments/{{ cookiecutter.environment_name }}/settings_merge.json with the default # config that was created when we built the openedx docker image with tutor - name: Patch Generated Configuration (Static) run: |- diff --git a/{{cookiecutter.github_repo_name}}/README.rst b/{{cookiecutter.github_repo_name}}/README.rst index 5e59a2e2..c67bed03 100644 --- a/{{cookiecutter.github_repo_name}}/README.rst +++ b/{{cookiecutter.github_repo_name}}/README.rst @@ -85,16 +85,40 @@ This repository was generated using `Cookiecutter `_ - {{ cookiecutter.ci_build_tutor_version }} + * - `Tutor Plugin: Object storage for Open edX with S3 `_ + - {{ cookiecutter.ci_deploy_hastexo_tutor_contrib_s3_version }} * - `Kubernetes Cluster `_ - - {{ cookiecutter.eks_cluster_version }} + - {{ cookiecutter.kubernetes_cluster_version }} * - Kubernetes `amazon/aws-alb-ingress-controller `_ - - {{ cookiecutter.eks_cluster_alb_ingress_controller_version }} + - {{ cookiecutter.kubernetes_cluster_ingress_controller_version }} * - `Terraform `_ - {{ cookiecutter.terraform_required_version }} + * - `terraform-aws-modules/acm `_ + - {{ cookiecutter.terraform_aws_modules_acm }} + * - `terraform-aws-modules/cloudfront `_ + - {{ cookiecutter.terraform_aws_modules_cloudfront }} + * - `terraform-aws-modules/eks `_ + - {{ cookiecutter.terraform_aws_modules_eks }} + * - `terraform-aws-modules/iam `_ + - {{ cookiecutter.terraform_aws_modules_iam }} + * - `terraform-aws-modules/rds `_ + - {{ cookiecutter.terraform_aws_modules_rds }} + * - `terraform-aws-modules/s3-bucket `_ + - {{ cookiecutter.terraform_aws_modules_s3 }} + * - `terraform-aws-modules/security-group `_ + - {{ cookiecutter.terraform_aws_modules_sg }} + * - `terraform-aws-modules/vpc `_ + - {{ cookiecutter.terraform_aws_modules_vpc }} + * - Terraform `Helm ingress-alb-controller `_ + - {{ cookiecutter.terraform_helm_alb_controller_chart_version }} + * - Terraform `Helm cert-manager `_ + - {{ cookiecutter.terraform_helm_cert_manager }} * - Terraform `Kubernetes Provider `_ - {{ cookiecutter.terraform_provider_kubernetes_version }} * - Terraform `AWS Provider `_ - {{ cookiecutter.terraform_provider_hashicorp_aws_version }} + * - Terraform `Helm Provider `_ + - {{ cookiecutter.terraform_provider_hashicorp_helm_version }} * - Terraform `Local Provider `_ - {{ cookiecutter.terraform_provider_hashicorp_local_version }} * - Terraform `Random Provider `_ @@ -110,7 +134,7 @@ Important Considerations - the Github Actions workflows depend on secrets `located here (see 'secrets/actions' from the left menu bar) `_ - the Github Actions use an AWS IAM key pair from `this manually-created user named *ci* `_ - the collection of resources created by these scripts **will generate AWS costs of around $0.41 USD per hour ($10.00 USD per day)** while the platform is in a mostly-idle pre-production state. This cost will grow proportionally to your production work loads. You can view your `AWS Billing dashboard here `_ -- **BE ADVISED** that `MySQL RDS `_, `MongoDB `_ and `Redis ElastiCache `_ are vertically scaled **manually** and therefore require some insight and potential adjustments on your part. All of these services are defaulted to their minimum instance sizes which you can modify in the `environment configuration file `_ +- **BE ADVISED** that `MySQL RDS `_, `MongoDB `_ and `Redis ElastiCache `_ are vertically scaled **manually** and therefore require some insight and potential adjustments on your part. All of these services are defaulted to their minimum instance sizes which you can modify in the `environment configuration file `_ Quick Start ----------- @@ -142,7 +166,7 @@ Set your `global parameters `_ } -Set your `production environment parameters `_ +Set your `production environment parameters `_ .. code-block:: hcl @@ -184,29 +208,25 @@ We also recommend that you install `k9s `_, a popular tool f .. code-block:: shell # ------------------------------------- - # to manage an individual resource + # to build the entire backend # ------------------------------------- - cd ./terraform/environments/prod/mongodb - terragrunt init - terragrunt plan - terragrunt apply - terragrunt destroy + cd ./terraform/environments/{{ cookiecutter.environment_name }}/vpc + terragrunt run-all init + terragrunt run-all apply # ------------------------------------- - # to build the entire backend + # or, to manage an individual resource # ------------------------------------- - - # 1. create the VPC - cd ./terraform/environments/prod/vpc + cd ./terraform/environments/{{ cookiecutter.environment_name }}/mongodb + terragrunt init + terragrunt validate + terragrunt plan terragrunt apply + terragrunt destroy - # 2. create the Elastic Kubernetes Cluster - cd ../eks - terragrunt apply - - # 3. create everthing else - cd .. - terragrunt run-all apply +.. image:: doc/terragrunt-init.png + :width: 900 + :alt: terragrunt run-all init IV. Connect To Your backend Services @@ -250,7 +270,7 @@ II. Deploy your Docker Image to a Kubernetes Cluster ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use `this automated Github Actions workflow `_ to deploy your customized Docker container to a Kubernetes Cluster. -Open edX LMS and Studio configuration parameters are located `here `_. +Open edX LMS and Studio configuration parameters are located `here `_. About The Open edX Platform Back End @@ -265,18 +285,63 @@ These scripts will create the following resources in your AWS account: - **Compute Cluster**. uses either `AWS EC2 `_ behind a Classic Load Balancer (the default) or AWS' serverless compute cluster, `Fargate `_ behind an Application Load Balancer. - **Kubernetes**. Uses `AWS Elastic Kubernetes Service `_ to implement a Kubernetes cluster onto which all applications and scheduled jobs are deployed as pods. -- **MySQL**. uses `AWS RDS `_ for all MySQL data, accessible inside the vpc as mysql.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}:3306. Instance size settings are located in the `environment configuration file `_, and other common configuration settings `are located here `_. Passwords are stored in `Kubernetes Secrets `_ accessible from the EKS cluster. -- **MongoDB**. uses `AWS DocumentDB `_ for all MongoDB data, accessible insid the vpc as mongodb.master.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}:27017 and mongodb.reader.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}. Instance size settings are located in the `environment configuration file `_, and other common configuration settings `are located here `_. Passwords are stored in `Kubernetes Secrets `_ accessible from the EKS cluster. -- **Redis**. uses `AWS ElastiCache `_ for all Django application caches, accessible inside the vpc as cache.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}. Instance size settings are located in the `environment configuration file `_. This is necessary in order to make the Open edX application layer completely ephemeral. Most importantly, user's login session tokens are persisted in Redis and so these need to be accessible to all app containers from a single Redis cache. Common configuration settings `are located here `_. Passwords are stored in `Kubernetes Secrets `_ accessible from the EKS cluster. -- **Container Registry**. uses this `automated Github Actions workflow <.github/workflows/tutor_build_image.yml>`_ to build your `tutor Open edX container `_ and then register it in `Amazon Elastic Container Registry (Amazon ECR) `_. Uses this `automated Github Actions workflow <.github/workflows/tutor_deploy_prod.yml>`_ to deploy your container to `AWS Amazon Elastic Kubernetes Service (EKS) `_. EKS worker instance size settings are located in the `environment configuration file `_. Note that tutor provides out-of-the-box support for Kubernetes. Terraform leverages Elastic Kubernetes Service to create a Kubernetes cluster onto which all services are deployed. Common configuration settings `are located here `_ -- **User Data**. uses `AWS S3 `_ for storage of user data. This installation makes use of a `Tutor plugin to offload object storage `_ from the Ubuntu file system to AWS S3. It creates a public read-only bucket named of the form {{ cookiecutter.environment_name }}-{{ cookiecutter.global_platform_name }}-{{ cookiecutter.global_platform_region }}-storage, with write access provided to edxapp so that app-generated static content like user profile images, xblock-generated file content, application badges, e-commerce pdf receipts, instructor grades downloads and so on will be saved to this bucket. This is not only a necessary step for making your application layer ephemeral but it also facilitates the implementation of a CDN (which Terraform implements for you). Terraform additionally implements a completely separate, more secure S3 bucket for archiving your daily data backups of MySQL and MongoDB. Common configuration settings `are located here `_ -- **CDN**. uses `AWS Cloudfront `_ as a CDN, publicly acccessible as https://cdn.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}. Terraform creates Cloudfront distributions for each of your enviornments. These are linked to the respective public-facing S3 Bucket for each environment, and the requisite SSL/TLS ACM-issued certificate is linked. Terraform also automatically creates all Route53 DNS records of form cdn.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}. Common configuration settings `are located here `_ -- **Password & Secrets Management** uses `Kubernetes Secrets `_ in the EKS cluster. Open edX software relies on many passwords and keys, collectively referred to in this documentation simply as, "*secrets*". For all back services, including all Open edX applications, system account and root passwords are randomly and strongluy generated during automated deployment and then archived in EKS' secrets repository. This methodology facilitates routine updates to all of your passwords and other secrets, which is good practice these days. Common configuration settings `are located here `_ -- **SSL Certs**. Uses `AWS Certificate Manager `_ and LetsEncrypt. Terraform creates all SSL/TLS certificates. It uses a combination of AWS Certificate Manager (ACM) as well as LetsEncrypt. Additionally, the ACM certificates are stored in two locations: your aws-region as well as in us-east-1 (as is required by AWS CloudFront). Common configuration settings `are located here `_ -- **DNS Management** uses `AWS Route53 `_ hosted zones for DNS management. Terraform expects to find your root domain already present in Route53 as a hosted zone. It will automatically create additional hosted zones, one per environment for production, dev, test and so on. It automatically adds NS records to your root domain hosted zone as necessary to link the zones together. Configuration data exists within several components but the highest-level settings `are located here `_ +- **MySQL**. uses `AWS RDS `_ for all MySQL data, accessible inside the vpc as mysql.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}:3306. Instance size settings are located in the `environment configuration file `_, and other common configuration settings `are located here `_. Passwords are stored in `Kubernetes Secrets `_ accessible from the EKS cluster. +- **MongoDB**. uses `AWS DocumentDB `_ for all MongoDB data, accessible insid the vpc as mongodb.master.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}:27017 and mongodb.reader.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}. Instance size settings are located in the `environment configuration file `_, and other common configuration settings `are located here `_. Passwords are stored in `Kubernetes Secrets `_ accessible from the EKS cluster. +- **Redis**. uses `AWS ElastiCache `_ for all Django application caches, accessible inside the vpc as cache.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}. Instance size settings are located in the `environment configuration file `_. This is necessary in order to make the Open edX application layer completely ephemeral. Most importantly, user's login session tokens are persisted in Redis and so these need to be accessible to all app containers from a single Redis cache. Common configuration settings `are located here `_. Passwords are stored in `Kubernetes Secrets `_ accessible from the EKS cluster. +- **Container Registry**. uses this `automated Github Actions workflow <.github/workflows/tutor_build_image.yml>`_ to build your `tutor Open edX container `_ and then register it in `Amazon Elastic Container Registry (Amazon ECR) `_. Uses this `automated Github Actions workflow <.github/workflows/tutor_deploy_prod.yml>`_ to deploy your container to `AWS Amazon Elastic Kubernetes Service (EKS) `_. EKS worker instance size settings are located in the `environment configuration file `_. Note that tutor provides out-of-the-box support for Kubernetes. Terraform leverages Elastic Kubernetes Service to create a Kubernetes cluster onto which all services are deployed. Common configuration settings `are located here `_ +- **User Data**. uses `AWS S3 `_ for storage of user data. This installation makes use of a `Tutor plugin to offload object storage `_ from the Ubuntu file system to AWS S3. It creates a public read-only bucket named of the form {{ cookiecutter.environment_name }}-{{ cookiecutter.global_platform_name }}-{{ cookiecutter.global_platform_region }}-storage, with write access provided to edxapp so that app-generated static content like user profile images, xblock-generated file content, application badges, e-commerce pdf receipts, instructor grades downloads and so on will be saved to this bucket. This is not only a necessary step for making your application layer ephemeral but it also facilitates the implementation of a CDN (which Terraform implements for you). Terraform additionally implements a completely separate, more secure S3 bucket for archiving your daily data backups of MySQL and MongoDB. Common configuration settings `are located here `_ +- **CDN**. uses `AWS Cloudfront `_ as a CDN, publicly acccessible as https://cdn.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}. Terraform creates Cloudfront distributions for each of your enviornments. These are linked to the respective public-facing S3 Bucket for each environment, and the requisite SSL/TLS ACM-issued certificate is linked. Terraform also automatically creates all Route53 DNS records of form cdn.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}. Common configuration settings `are located here `_ +- **Password & Secrets Management** uses `Kubernetes Secrets `_ in the EKS cluster. Open edX software relies on many passwords and keys, collectively referred to in this documentation simply as, "*secrets*". For all back services, including all Open edX applications, system account and root passwords are randomly and strongluy generated during automated deployment and then archived in EKS' secrets repository. This methodology facilitates routine updates to all of your passwords and other secrets, which is good practice these days. Common configuration settings `are located here `_ +- **SSL Certs**. Uses `AWS Certificate Manager `_ and LetsEncrypt. Terraform creates all SSL/TLS certificates. It uses a combination of AWS Certificate Manager (ACM) as well as LetsEncrypt. Additionally, the ACM certificates are stored in two locations: your aws-region as well as in us-east-1 (as is required by AWS CloudFront). Common configuration settings `are located here `_ +- **DNS Management** uses `AWS Route53 `_ hosted zones for DNS management. Terraform expects to find your root domain already present in Route53 as a hosted zone. It will automatically create additional hosted zones, one per environment for production, dev, test and so on. It automatically adds NS records to your root domain hosted zone as necessary to link the zones together. Configuration data exists within several modules but the highest-level settings `are located here `_ - **System Access** uses `AWS Identity and Access Management (IAM) `_ to manage all system users and roles. Terraform will create several user accounts with custom roles, one or more per service. -- **Network Design**. uses `Amazon Virtual Private Cloud (Amazon VPC) `_ based on the AWS account number provided in the `global configuration file `_ to take a top-down approach to compartmentalize all cloud resources and to customize the operating enviroment for your Open edX resources. Terraform will create a new virtual private cloud into which all resource will be provisioned. It creates a sensible arrangment of private and public subnets, network security settings and security groups. See additional VPC documentation `here `_ -- **Proxy Access to Backend Services**. uses an `Amazon EC2 `_ t2.micro Ubuntu instance publicly accessible via ssh as bastion.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}:22 using the ssh key specified in the `global configuration file `_. For security as well as performance reasons all backend services like MySQL, Mongo, Redis and the Kubernetes cluster are deployed into their own private subnets, meaning that none of these are publicly accessible. See additional Bastion documentation `here `_. Terraform creates a t2.micro EC2 instance to which you can connect via ssh. In turn you can connect to services like MySQL via the bastion. Common configuration settings `are located here `_. Note that if you are cost conscious then you could alternatively use `AWS Cloud9 `_ to gain access to all backend services. +- **Network Design**. uses `Amazon Virtual Private Cloud (Amazon VPC) `_ based on the AWS account number provided in the `global configuration file `_ to take a top-down approach to compartmentalize all cloud resources and to customize the operating enviroment for your Open edX resources. Terraform will create a new virtual private cloud into which all resource will be provisioned. It creates a sensible arrangment of private and public subnets, network security settings and security groups. See additional VPC documentation `here `_ +- **Proxy Access to Backend Services**. uses an `Amazon EC2 `_ t2.micro Ubuntu instance publicly accessible via ssh as bastion.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}:22 using the ssh key specified in the `global configuration file `_. For security as well as performance reasons all backend services like MySQL, Mongo, Redis and the Kubernetes cluster are deployed into their own private subnets, meaning that none of these are publicly accessible. See additional Bastion documentation `here `_. Terraform creates a t2.micro EC2 instance to which you can connect via ssh. In turn you can connect to services like MySQL via the bastion. Common configuration settings `are located here `_. Note that if you are cost conscious then you could alternatively use `AWS Cloud9 `_ to gain access to all backend services. + +Fargate Release Notes +--------------------- + +Fargate is a serverless compute alternative to EC2 instances. This is an **experimental** part of the Open edX devops stack. While the Fargate compute service itself +is both stable and robust, it's integration with Terraform for purposes providing the compute layer for a kubernetes cluster is a relatively new thing, and comes with some headaches. +For the avoidance of any doubt, Fargate runs well inside a Kubernetes cluster and for the most part is indistinguishable from a traditional EC2 server, aside from the obvious luxury of not needing to +directly administer this aspect of the cluster. But on the other hand, Terraform's life cycle management of a kubernetes cluster running Fargate is imperfect. Before you deploy Fargate into a production +environment please consider the following: + +Known Issues +~~~~~~~~~~~~ + +- When using Terraform to create an EKS Kubernetes Cluster configured to use Fargate, the apply operation will fail on your first attempt. See error message below. This is a known issue that is caused by a race condition between coredns and creation of the Fargate node on which it runs. Re-attempting with `terragrunt apply` resolves the problem. +- When using Terraform to destroy an EKS Kubernetes Cluster configured to use Fargate instead of EC2, you might experience any of the following: + + a) Terraform fails to destroy some of the IAM roles when destroying the EKS. Each is an eks Service-Linked Role. This is a known bug in the Terraform module. + b) Terraform fails to destroy one or more of the EKS security groups. This is a known bug in the Terraform module. + +- Terraform fails to destroy the Application Load Balancer ingress. This is due to a dependency problem which I'm still trouble shooting. The temporary resolution is to delete the Terraform file `terraform/modules/kubernetes_ingress_alb_controller/ingress.tf` and then run `terraform apply`. +- Other AWS admin users might lack permissions to view EKS resources in the AWS console, even if they have `admin` permissions or are logged in as the root account user. This is an AWS issue. I'm working on a set of instructions for configuring permissions for other users. +- If Terraform is interrupted during execution then it is possible that it will lose track of its state, leading to Terraform attempting to create already-existing resources which will result in run-time errors. This is the expected behavior of Terraform, but it can be a huge pain in the neck to resolve. + +Build Error +~~~~~~~~~~~ + +On your first build attempt you will encounter the following error aproximately 30 minutes into the kubernetes build. This is a know bug caused by a race condition in coredns installation when it is configured to run on Fargate nodes rather than EC2 instances. +Restarting the build resolves the error, and the build should complete normally. + +.. code-block:: bash + + module.eks.aws_eks_addon.this["coredns"]: Still creating... [20m0s elapsed] + â•· + │ Error: unexpected EKS Add-On (prod-stepwisemath-mexico:coredns) state returned during creation: timeout while waiting for state to become 'ACTIVE' (last state: 'DEGRADED', timeout: 20m0s) + │ [WARNING] Running terraform apply again will remove the kubernetes add-on and attempt to create it again effectively purging previous add-on configuration + │ + │ with module.eks.aws_eks_addon.this["coredns"], + │ on .terraform/modules/eks/main.tf line 298, in resource "aws_eks_addon" "this": + │ 298: resource "aws_eks_addon" "this" { + │ + ╵ + Releasing state lock. This may take a few moments... + ERRO[1950] 1 error occurred: + * exit status 1 + FAQ --- @@ -315,7 +380,7 @@ Behind the scenes Kubernetes (EKS in our case) uses an EC2 Elastic Load Balancer Why Use Terraform? ~~~~~~~~~~~~~~~~~~ -`Terraform `_ allows you to manage the entire lifecycle of your AWS cloud infrastructure using `infrastructure as code (IAC) `_. That means declaring infrastructure components in configuration files that are then used by Terraform to provision, adjust and tear down your AWS cloud infrastructure. There are tangential benefits to using IAC. +`Terraform `_ allows you to manage the entire lifecycle of your AWS cloud infrastructure using `infrastructure as code (IAC) `_. That means declaring infrastructure resources in configuration files that are then used by Terraform to provision, adjust and tear down your AWS cloud infrastructure. There are tangential benefits to using IAC. 1. **Maintain all of your backend configuration data in a single location**. This allows you to take a more holistic, top-down approach to planning and managing your backend resources, which leads to more reliable service for your users. 2. **Leverage git**. This is a big deal! Managing your backend as IAC means you can track individual changes to your configuration over time. More importantly, it means you can reverse backend configuration changes that didn't go as planned. diff --git a/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_clb_ec2/README.md b/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/README.md similarity index 94% rename from {{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_clb_ec2/README.md rename to {{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/README.md index 3b3feabd..961af9d1 100644 --- a/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_clb_ec2/README.md +++ b/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/README.md @@ -48,7 +48,7 @@ Taking the `dev` environment as an example, the file structure looks like this: #### config.yml This file contains a few entries that will be fed into early the Tutor configuration stage. -These are the FQDNs of the LMS and CMS components of Open edX and the location of the custom image that we build [here](https://github.com/{{ cookiecutter.github_account_name }}/tutor-build). +These are the FQDNs of the LMS and CMS applications of Open edX and the location of the custom image that we build [here](https://github.com/{{ cookiecutter.github_account_name }}/tutor-build). #### k8s diff --git a/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_clb_ec2/cluster-issuer.yml b/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/cluster-issuer.yml similarity index 94% rename from {{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_clb_ec2/cluster-issuer.yml rename to {{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/cluster-issuer.yml index 6f06b952..b2082fe1 100644 --- a/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_clb_ec2/cluster-issuer.yml +++ b/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/cluster-issuer.yml @@ -29,7 +29,7 @@ kind: Certificate metadata: name: le-crt spec: - secretName: wild-openedx-prod-tls + secretName: wild-openedx-{{ cookiecutter.environment_name }}-tls issuerRef: kind: ClusterIssuer name: letsencrypt diff --git a/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_alb_ec2/README.md b/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_alb_ec2/README.md deleted file mode 100644 index ecb21132..00000000 --- a/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_alb_ec2/README.md +++ /dev/null @@ -1,68 +0,0 @@ -# Tutor Deploy to EKS With ALB - -## Open edX Tutor Deployment -This repository contains a set of GitHub actions workflows to deploy Tutor's Open edX onto our [Kubenetes (EKS) cluster](https://github.com/{{ cookiecutter.github_account_name }}/terraform-aws). - - -## How it works -All the logic is defined in the actual workflow. It mostly follows the steps outlined on Tutor's documentation with some adaptations to run it in a disposable CI environment. - -When running the Tutor CLI on a local machine it can run in an interactive mode and persists the captured config into a local file. In the context of a CI job, such as GitHub Actions, this is not possible. - -Luckily the Tutor CLI allows all of it's params to be passed as a command line argument, or as an environment variable. We leverage this feature to provide all the custom details, from external sources. - - -## Dependencies -This workflow needs to collect some parameters for Tutor from external sources, such as credentials and endpoints from backing services. As a rule of thumb these are fetched from a predefined Kubernetes secret resource on the target namespace for the environment. - -Also, the backing services need to be readily available prior to deploying the Open edX platform, because Tutor and the workflow will need to run several initialisation tasks; Django database migrations for example. - -All the necessary dependencies need to be deployed prior to deploying an environment for the first time using the terraform stack in [this repo](https://github.com/{{ cookiecutter.github_account_name }}/terraform-aws) and [this repo](https://github.com/{{ cookiecutter.github_account_name }}/terraform-openedx). - -The Terraform stack will create all of the resources needed for this deployment workflow to operate and deliver a running edX platform. -- Kubernetes namespace -- Mysql database (RDS) -- ElasticSearch (AWS ElasticSearch) -- MCDANIEL: REMOVED FEB-2022 -- Redis (AWS ElasticCache Redis) -- S3 Bucket -- Kubernetes' secrets containing the locations and credentials for all the above AWS services and others - - -## Deployment process -Once the Terraform stack with the Open edX dependencies has been successfully applied for a particular Open edX environment (one-off) we just need to trigger the desired environment's workflow dispatch. - -### Repository structure -This repository contains a directory `environemnts` with the following structure - -Taking the `dev` environment as an example, the file structure looks like this: - -``` -└── environments -├── dev -│ ├── config.yml -│ ├── k8s -│ │ ├── cluster-issuer.yml -│ │ └── ingress.yml -│ └── settings_merge.json -``` - -#### config.yml -This file contains a few entries that will be fed into early the Tutor configuration stage. -These are the FQDNs of the LMS and CMS components of Open edX and the location of the custom image that we build [here](https://github.com/{{ cookiecutter.github_account_name }}/tutor-build). - -#### k8s - -This is a directory that contains predefined Kubernetes resources to deploy edX - - ├── cluster-issuer.yml - └── ingress.yml - -This is a definition of a ClusterIssuer and a TLS Certificate. -These resources create a Kubernetes ingress with TLS support and generate a TLS certificate to match the associated domain. -They are applied and enforced during the deployment. - -#### settings_merge.json -This file contains custom configuration that is not managed by Tutor, but that we need to add to the running Open edX services so that our plugin can work. - -We cannot tell Tutor to include extra configuration or settings that it does not manage, -so we will merge this JSON block to the final rendered configuration that will be passed on to the edX services ,the LMS and the CMS. diff --git a/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_alb_fargate/README.md b/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_alb_fargate/README.md deleted file mode 100644 index e60d0517..00000000 --- a/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_alb_fargate/README.md +++ /dev/null @@ -1,68 +0,0 @@ -# Tutor Deploy to EKS Fargate - -## Open edX Tutor Deployment -This repository contains a set of GitHub actions workflows to deploy Tutor's Open edX onto our [Kubenetes (EKS) cluster](https://github.com/{{ cookiecutter.github_account_name }}/terraform-aws). - - -## How it works -All the logic is defined in the actual workflow. It mostly follows the steps outlined on Tutor's documentation with some adaptations to run it in a disposable CI environment. - -When running the Tutor CLI on a local machine it can run in an interactive mode and persists the captured config into a local file. In the context of a CI job, such as GitHub Actions, this is not possible. - -Luckily the Tutor CLI allows all of it's params to be passed as a command line argument, or as an environment variable. We leverage this feature to provide all the custom details, from external sources. - - -## Dependencies -This workflow needs to collect some parameters for Tutor from external sources, such as credentials and endpoints from backing services. As a rule of thumb these are fetched from a predefined Kubernetes secret resource on the target namespace for the environment. - -Also, the backing services need to be readily available prior to deploying the Open edX platform, because Tutor and the workflow will need to run several initialisation tasks; Django database migrations for example. - -All the necessary dependencies need to be deployed prior to deploying an environment for the first time using the terraform stack in [this repo](https://github.com/{{ cookiecutter.github_account_name }}/terraform-aws) and [this repo](https://github.com/{{ cookiecutter.github_account_name }}/terraform-openedx). - -The Terraform stack will create all of the resources needed for this deployment workflow to operate and deliver a running edX platform. -- Kubernetes namespace -- Mysql database (RDS) -- ElasticSearch (AWS ElasticSearch) -- MCDANIEL: REMOVED FEB-2022 -- Redis (AWS ElasticCache Redis) -- S3 Bucket -- Kubernetes' secrets containing the locations and credentials for all the above AWS services and others - - -## Deployment process -Once the Terraform stack with the Open edX dependencies has been successfully applied for a particular Open edX environment (one-off) we just need to trigger the desired environment's workflow dispatch. - -### Repository structure -This repository contains a directory `environemnts` with the following structure - -Taking the `dev` environment as an example, the file structure looks like this: - -``` -└── environments -├── dev -│ ├── config.yml -│ ├── k8s -│ │ ├── cluster-issuer.yml -│ │ └── ingress.yml -│ └── settings_merge.json -``` - -#### config.yml -This file contains a few entries that will be fed into early the Tutor configuration stage. -These are the FQDNs of the LMS and CMS components of Open edX and the location of the custom image that we build [here](https://github.com/{{ cookiecutter.github_account_name }}/tutor-build). - -#### k8s - -This is a directory that contains predefined Kubernetes resources to deploy edX - - ├── cluster-issuer.yml - └── ingress.yml - -This is a definition of a ClusterIssuer and a TLS Certificate. -These resources create a Kubernetes ingress with TLS support and generate a TLS certificate to match the associated domain. -They are applied and enforced during the deployment. - -#### settings_merge.json -This file contains custom configuration that is not managed by Tutor, but that we need to add to the running Open edX services so that our plugin can work. - -We cannot tell Tutor to include extra configuration or settings that it does not manage, -so we will merge this JSON block to the final rendered configuration that will be passed on to the edX services ,the LMS and the CMS. diff --git a/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_clb_ec2/data-backup.yml b/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_clb_ec2/data-backup.yml deleted file mode 100644 index 2c40e05e..00000000 --- a/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_clb_ec2/data-backup.yml +++ /dev/null @@ -1,102 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Lawrence McDaniel -# https://lawrencemcdaniel.com/ -# -# date: Feb-2022 -# -# usage: Dumps mysql and mongo. stores the completed backups in AWS S3 -#------------------------------------------------------------------------------ -apiVersion: batch/v1beta1 -kind: CronJob -metadata: - name: data-backup - namespace: {{ cookiecutter.environment_name }}-{{ cookiecutter.global_platform_name }}-{{ cookiecutter.global_platform_region }} -spec: - schedule: "0 8 * * *" - jobTemplate: - spec: - template: - spec: - containers: - - name: mongodb - image: docker.io/mongo:4.0.25 - imagePullPolicy: IfNotPresent - command: - - /bin/sh - - -c - - |- - echo "Backup MongoDB" - apt-get update && apt-get install -y curl unzip - curl -s "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" - unzip -q awscliv2.zip - ./aws/install - mongodump --host="mongodb:27017" - DATE=$(date +%Y%m%d-%H%M) && echo $DATE - MONGO_FILE="mongodump-$DATE" - mv dump $MONGO_FILE - aws s3 sync $MONGO_FILE s3://$S3_BUCKET/$MONGO_FILE/ - env: - - name: AWS_ACCESS_KEY_ID - valueFrom: - secretKeyRef: - name: s3-data-backup-web - key: AWS_ACCESS_KEY_ID - - name: AWS_SECRET_ACCESS_KEY - valueFrom: - secretKeyRef: - name: s3-data-backup-web - key: AWS_SECRET_ACCESS_KEY - - name: S3_BUCKET - valueFrom: - secretKeyRef: - name: s3-data-backup-web - key: S3_BUCKET - - name: mysql - image: docker.io/mysql:5.7.33 - imagePullPolicy: IfNotPresent - command: - - /bin/sh - - -c - - |- - echo "Backup MySQL" - apt-get update && apt-get install -y curl unzip - curl -s "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" - unzip -q awscliv2.zip - ./aws/install - DATE=$(date +%Y%m%d-%H%M) && echo $DATE - SQL_FILE="mysqldump-$DATE" - mysqldump -h"$MYSQL_HOST" -u"$MYSQL_ROOT_USERNAME" -p"$MYSQL_ROOT_PASSWORD" --add-drop-database --set-gtid-purged=OFF --column-statistics=0 openedx > ${SQL_FILE} - aws s3 sync $SQL_FILE s3://$S3_BUCKET/$SQL_FILE/ - env: - - name: AWS_ACCESS_KEY_ID - valueFrom: - secretKeyRef: - name: s3-data-backup-web - key: AWS_ACCESS_KEY_ID - - name: AWS_SECRET_ACCESS_KEY - valueFrom: - secretKeyRef: - name: s3-data-backup-web - key: AWS_SECRET_ACCESS_KEY - - name: S3_BUCKET - valueFrom: - secretKeyRef: - name: s3-data-backup-web - key: S3_BUCKET - - name: MYSQL_HOST - valueFrom: - secretKeyRef: - name: sql-root - key: MYSQL_HOST - - name: MYSQL_ROOT_USERNAME - valueFrom: - secretKeyRef: - name: sql-root - key: MYSQL_ROOT_USERNAME - - name: MYSQL_ROOT_PASSWORD - valueFrom: - secretKeyRef: - name: sql-root - key: MYSQL_ROOT_PASSWORD - - restartPolicy: OnFailure diff --git a/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_clb_ec2/ingress.yml b/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/ingress.yml similarity index 91% rename from {{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_clb_ec2/ingress.yml rename to {{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/ingress.yml index e80d0f87..6422bb58 100644 --- a/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/eks_clb_ec2/ingress.yml +++ b/{{cookiecutter.github_repo_name}}/ci/tutor-deploy/environments/{{cookiecutter.environment_name}}/k8s/ingress.yml @@ -10,7 +10,7 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: openedx - namespace: {{ cookiecutter.environment_name }}-{{ cookiecutter.global_platform_name }}-{{ cookiecutter.global_platform_region }} + namespace: openedx annotations: # mcdaniel # https://www.cyberciti.biz/faq/nginx-upstream-sent-too-big-header-while-reading-response-header-from-upstream/ @@ -28,7 +28,7 @@ spec: - hosts: - "{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}" - "*.{{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }}" - secretName: wild-openedx-prod-tls + secretName: wild-openedx-{{ cookiecutter.environment_name }}-tls rules: - host: {{ cookiecutter.environment_subdomain }}.{{ cookiecutter.global_root_domain }} http: diff --git a/{{cookiecutter.github_repo_name}}/doc/terragrunt-init.png b/{{cookiecutter.github_repo_name}}/doc/terragrunt-init.png new file mode 100644 index 00000000..2ac7ebe1 Binary files /dev/null and b/{{cookiecutter.github_repo_name}}/doc/terragrunt-init.png differ diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/kubernetes.tf b/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/kubernetes.tf deleted file mode 100644 index 5a7e725c..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/kubernetes.tf +++ /dev/null @@ -1,37 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: create a non-public S3 Bucket to store data backups from any backend -# service. -# -# store S3 credentials (key/secret pair) in EKS Kubernetes Secrets. -#------------------------------------------------------------------------------ -data "aws_eks_cluster" "eks" { - name = var.environment_namespace -} - -data "aws_eks_cluster_auth" "eks" { - name = var.environment_namespace -} - -provider "kubernetes" { - host = data.aws_eks_cluster.eks.endpoint - cluster_ca_certificate = base64decode(data.aws_eks_cluster.eks.certificate_authority[0].data) - token = data.aws_eks_cluster_auth.eks.token -} - -resource "kubernetes_secret" "s3" { - metadata { - name = var.secret_name - namespace = var.environment_namespace - } - - data = { - AWS_ACCESS_KEY_ID = aws_iam_access_key.user.id - AWS_SECRET_ACCESS_KEY = aws_iam_access_key.user.secret - S3_BUCKET = module.data_backup_s3_bucket.s3_bucket_id - } -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/main.tf b/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/main.tf deleted file mode 100644 index afe08f37..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/main.tf +++ /dev/null @@ -1,62 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: create a non-public S3 Bucket to store data backups from any backend -# service. -#------------------------------------------------------------------------------ -module "data_backup_s3_bucket" { - source = "terraform-aws-modules/s3-bucket/aws" - version = "~> 2" - - bucket = var.resource_name - acl = "private" - - control_object_ownership = true - object_ownership = "BucketOwnerPreferred" - - versioning = { - enabled = false - } -} - -# Generate an additional IAM user with read-only access to the bucket -resource "random_id" "id" { - byte_length = 16 -} - -resource "aws_iam_user" "user" { - name = "s3-openedx-user-${random_id.id.hex}" - path = "/system/s3-bucket-user/" -} - -data "aws_iam_policy_document" "user_policy" { - statement { - actions = [ - "s3:*" - ] - resources = [ - module.data_backup_s3_bucket.s3_bucket_arn - ] - } - statement { - actions = [ - "s3:*" - ] - resources = [ - "${module.data_backup_s3_bucket.s3_bucket_arn}/*" - ] - } -} - -resource "aws_iam_access_key" "user" { - user = aws_iam_user.user.name -} - -resource "aws_iam_user_policy" "policy" { - name = "s3-bucket" - policy = data.aws_iam_policy_document.user_policy.json - user = aws_iam_user.user.name -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/outputs.tf b/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/outputs.tf deleted file mode 100644 index 30875f76..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/outputs.tf +++ /dev/null @@ -1,48 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: create a non-public S3 Bucket to store data backups from any backend -# service. -#------------------------------------------------------------------------------ -output "s3_bucket_id" { - description = "The name of the bucket." - value = module.data_backup_s3_bucket.s3_bucket_id -} - -output "s3_bucket_arn" { - description = "The ARN of the bucket. Will be of format arn:aws:s3:::bucketname." - value = module.data_backup_s3_bucket.s3_bucket_arn -} - -output "s3_bucket_bucket_domain_name" { - description = "The bucket domain name. Will be of format bucketname.s3.amazonaws.com." - value = module.data_backup_s3_bucket.s3_bucket_bucket_domain_name -} - -output "s3_bucket_bucket_regional_domain_name" { - description = "The bucket region-specific domain name. The bucket domain name including the region name, please refer here for format. Note: The AWS CloudFront allows specifying S3 region-specific endpoint when creating S3 origin, it will prevent redirect issues from CloudFront to S3 Origin URL." - value = module.data_backup_s3_bucket.s3_bucket_bucket_regional_domain_name -} - -output "s3_bucket_hosted_zone_id" { - description = "The Route 53 Hosted Zone ID for this bucket's region." - value = module.data_backup_s3_bucket.s3_bucket_hosted_zone_id -} - -output "s3_bucket_region" { - description = "The AWS region this bucket resides in." - value = module.data_backup_s3_bucket.s3_bucket_region -} - -output "s3_bucket_website_endpoint" { - description = "The website endpoint, if the bucket is configured with a website. If not, this will be an empty string." - value = module.data_backup_s3_bucket.s3_bucket_website_endpoint -} - -output "s3_bucket_website_domain" { - description = "The domain of the website endpoint, if the bucket is configured with a website. If not, this will be an empty string. This is used to create Route 53 alias records. " - value = module.data_backup_s3_bucket.s3_bucket_website_domain -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/variables.tf deleted file mode 100644 index 9e728b44..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/variables.tf +++ /dev/null @@ -1,47 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: create a non-public S3 Bucket to store data backups from any backend -# service. -#------------------------------------------------------------------------------ -variable "bucket_name" { - description = "Name of the Open edX S3 bucket" - type = string - default = null -} - -variable "secret_name" { - description = "name of the kubernetes secret where the value is stored" - type = string -} - -variable "environment_namespace" { - description = "kubernetes namespace where to place resources" - type = string -} - - -variable "environment_domain" { - description = "base domain for service" - type = string -} - -variable "environment" { - description = "environment name" - type = string -} - -variable "resource_name" { - description = "the full environment-qualified name of this resource." - type = string -} - - -variable "tags" { - description = "collection of all tags to add to this resource. execting the combination of global + environment + resouce tags." - type = map(string) - default = {} -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/versions.tf deleted file mode 100644 index ad91a051..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/data_backup_s3/versions.tf +++ /dev/null @@ -1,19 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: create a non-public S3 Bucket to store data backups from any backend -# service. -#------------------------------------------------------------------------------ -terraform { - required_version = "{{ cookiecutter.terraform_required_version }}" - - required_providers { - aws = { - source = "hashicorp/aws" - version = "{{ cookiecutter.terraform_provider_hashicorp_aws_version }}" - } - } -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/acm.tf b/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/acm.tf deleted file mode 100644 index 88021d04..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/acm.tf +++ /dev/null @@ -1,83 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Lawrence McDaniel -# https://lawrencemcdaniel.com/ -# -# date: Feb-2022 -# -# usage: Add tls certs to us-east-1 for Cloudfront distributions. -# -# we have to add these here, inside of eks because we -# need to iterate the subdomains, and this is only possible -# within the terragrunt module in which the subdomain -# resources are created. -# -# that is, the following line only works from -# inside eks: -# aws_route53_zone.subdomain[count.index].name -# -# where aws_route53_zone was declared as a resource rather -# than as data -#------------------------------------------------------------------------------ - -provider "aws" { - alias = "us-east-1" - region = "us-east-1" -} - -module "acm_root_domain" { - source = "terraform-aws-modules/acm/aws" - version = "~> 3.0" - - providers = { - aws = aws.us-east-1 - } - - domain_name = var.root_domain - zone_id = data.aws_route53_zone.root_domain.id - - subject_alternative_names = [ - "*.${var.root_domain}", - ] - - wait_for_validation = true - tags = var.tags -} - -module "acm_environment_domain" { - source = "terraform-aws-modules/acm/aws" - version = "~> 3.0" - - providers = { - aws = aws.us-east-1 - } - - domain_name = var.environment_domain - zone_id = data.aws_route53_zone.environment_domain.id - - subject_alternative_names = [ - "*.${var.environment_domain}", - ] - - wait_for_validation = true - tags = var.tags -} - -module "acm_subdomains" { - source = "terraform-aws-modules/acm/aws" - version = "~> 3.0" - - providers = { - aws = aws.us-east-1 - } - - count = length(var.subdomains) - domain_name = aws_route53_zone.subdomain[count.index].name - zone_id = aws_route53_zone.subdomain[count.index].id - - subject_alternative_names = [ - "*.${aws_route53_zone.subdomain[count.index].name}", - ] - - wait_for_validation = true - tags = var.tags -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/main.tf b/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/main.tf deleted file mode 100644 index 92eab56e..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/main.tf +++ /dev/null @@ -1,105 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: build an EKS cluster load balancer -#------------------------------------------------------------------------------ -locals { - name = var.cluster_name - tags = var.tags -} - -data "aws_eks_cluster" "cluster" { - name = module.eks.cluster_id -} - -data "aws_eks_cluster_auth" "cluster" { - name = module.eks.cluster_id -} - -provider "kubernetes" { - host = data.aws_eks_cluster.cluster.endpoint - cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data) - token = data.aws_eks_cluster_auth.cluster.token - load_config_file = false -} - -resource "aws_security_group" "worker_group_mgmt" { - name_prefix = "${var.environment_namespace}-eks_worker_group_mgmt" - vpc_id = var.vpc_id - - ingress { - from_port = 22 - to_port = 22 - protocol = "tcp" - - cidr_blocks = [ - "10.0.0.0/8", - ] - } - - tags = var.tags - -} - -resource "aws_security_group" "all_worker_mgmt" { - name_prefix = "${var.environment_namespace}-eks_all_worker_management" - vpc_id = var.vpc_id - - ingress { - from_port = 22 - to_port = 22 - protocol = "tcp" - - cidr_blocks = [ - "10.0.0.0/8", - "172.16.0.0/12", - "192.168.0.0/16", - ] - } - - tags = var.tags - -} - -data "tls_certificate" "cluster" { - url = module.eks.cluster_oidc_issuer_url -} - - -resource "kubernetes_namespace" "namespace" { - metadata { - name = "openedx" - } -} - -module "eks" { - source = "terraform-aws-modules/eks/aws" - version = ">= 17.24.0, < 18.0.0" - cluster_name = local.name - cluster_version = var.cluster_version - subnets = var.subnets - vpc_id = var.vpc_id - enable_irsa = var.enable_irsa - manage_aws_auth = true - - worker_groups = [ - { - instance_type = var.worker_group_instance_type - asg_desired_capacity = var.worker_group_asg_min_size - asg_min_size = var.worker_group_asg_min_size - asg_max_size = var.worker_group_asg_max_size - additional_security_group_ids = [aws_security_group.worker_group_mgmt.id] - subnets = var.subnets - } - ] - - worker_additional_security_group_ids = [aws_security_group.all_worker_mgmt.id] - map_roles = var.map_roles - map_users = var.map_users - map_accounts = var.map_accounts - - tags = var.tags -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/outputs.tf b/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/outputs.tf deleted file mode 100644 index 05d87e62..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/outputs.tf +++ /dev/null @@ -1,186 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: build an EKS cluster load balancer -#------------------------------------------------------------------------------ -output "cluster_id" { - description = "The name/id of the EKS cluster. Will block on cluster creation until the cluster is really ready." - value = module.eks.cluster_id -} - -output "cluster_arn" { - description = "The Amazon Resource Name (ARN) of the cluster." - value = module.eks.cluster_arn -} - -output "cluster_certificate_authority_data" { - description = "Nested attribute containing certificate-authority-data for your cluster. This is the base64 encoded certificate data required to communicate with your cluster." - value = module.eks.cluster_certificate_authority_data -} - -output "cluster_endpoint" { - description = "The endpoint for your EKS Kubernetes API." - value = module.eks.cluster_endpoint -} - -output "cluster_version" { - description = "The Kubernetes server version for the EKS cluster." - value = module.eks.cluster_version -} - -output "cluster_security_group_id" { - description = "Security group ID attached to the EKS cluster. On 1.14 or later, this is the 'Additional security groups' in the EKS console." - value = module.eks.cluster_security_group_id -} - -output "config_map_aws_auth" { - description = "A kubernetes configuration to authenticate to this EKS cluster." - value = module.eks.config_map_aws_auth -} - -output "cluster_iam_role_name" { - description = "IAM role name of the EKS cluster." - value = module.eks.cluster_iam_role_name -} - -output "cluster_iam_role_arn" { - description = "IAM role ARN of the EKS cluster." - value = module.eks.cluster_iam_role_arn -} - -output "cluster_oidc_issuer_url" { - description = "The URL on the EKS cluster OIDC Issuer" - value = module.eks.cluster_oidc_issuer_url -} - -output "cluster_primary_security_group_id" { - description = "The cluster primary security group ID created by the EKS cluster on 1.14 or later. Referred to as 'Cluster security group' in the EKS console." - value = module.eks.cluster_primary_security_group_id -} - -output "cloudwatch_log_group_name" { - description = "Name of cloudwatch log group created" - value = module.eks.cloudwatch_log_group_name -} - -output "cloudwatch_log_group_arn" { - description = "Arn of cloudwatch log group created" - value = module.eks.cloudwatch_log_group_arn -} - -output "kubeconfig" { - description = "kubectl config file contents for this EKS cluster. Will block on cluster creation until the cluster is really ready." - value = module.eks.kubeconfig -} - -output "kubeconfig_filename" { - description = "The filename of the generated kubectl config. Will block on cluster creation until the cluster is really ready." - value = module.eks.kubeconfig_filename -} - -output "oidc_provider_arn" { - description = "The ARN of the OIDC Provider if `enable_irsa = true`." - value = module.eks.oidc_provider_arn -} - -output "workers_asg_arns" { - description = "IDs of the autoscaling groups containing workers." - value = module.eks.workers_asg_arns -} - -output "workers_asg_names" { - description = "Names of the autoscaling groups containing workers." - value = module.eks.workers_asg_names -} - -output "workers_user_data" { - description = "User data of worker groups" - value = module.eks.workers_user_data -} - -output "workers_default_ami_id" { - description = "ID of the default worker group AMI" - value = module.eks.workers_default_ami_id -} - -output "workers_default_ami_id_windows" { - description = "ID of the default Windows worker group AMI" - value = module.eks.workers_default_ami_id_windows -} - -output "workers_launch_template_ids" { - description = "IDs of the worker launch templates." - value = module.eks.workers_launch_template_ids -} - -output "workers_launch_template_arns" { - description = "ARNs of the worker launch templates." - value = module.eks.workers_launch_template_arns -} - -output "workers_launch_template_latest_versions" { - description = "Latest versions of the worker launch templates." - value = module.eks.workers_launch_template_latest_versions -} - -output "worker_security_group_id" { - description = "Security group ID attached to the EKS workers." - value = module.eks.worker_security_group_id -} - -output "worker_iam_instance_profile_arns" { - description = "default IAM instance profile ARN for EKS worker groups" - value = module.eks.worker_iam_instance_profile_arns -} - -output "worker_iam_instance_profile_names" { - description = "default IAM instance profile name for EKS worker groups" - value = module.eks.worker_iam_instance_profile_names -} - -output "worker_iam_role_name" { - description = "default IAM role name for EKS worker groups" - value = module.eks.worker_iam_role_name -} - -output "worker_iam_role_arn" { - description = "default IAM role ARN for EKS worker groups" - value = module.eks.worker_iam_role_arn -} - -output "fargate_profile_ids" { - description = "EKS Cluster name and EKS Fargate Profile names separated by a colon (:)." - value = module.eks.fargate_profile_ids -} - -output "fargate_profile_arns" { - description = "Amazon Resource Name (ARN) of the EKS Fargate Profiles." - value = module.eks.fargate_profile_arns -} - -output "fargate_iam_role_name" { - description = "IAM role name for EKS Fargate pods" - value = module.eks.fargate_iam_role_name -} - -output "fargate_iam_role_arn" { - description = "IAM role ARN for EKS Fargate pods" - value = module.eks.fargate_iam_role_arn -} - -output "node_groups" { - description = "Outputs from EKS node groups. Map of maps, keyed by var.node_groups keys" - value = module.eks.node_groups -} - -output "security_group_rule_cluster_https_worker_ingress" { - description = "Security group rule responsible for allowing pods to communicate with the EKS cluster API." - value = module.eks.security_group_rule_cluster_https_worker_ingress -} - -output "cert_manager_irsa_role_arn" { - value = module.cert_manager_irsa.iam_role_arn -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/variables.tf deleted file mode 100644 index 76802bbf..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/variables.tf +++ /dev/null @@ -1,105 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: build an EKS cluster load balancer -#------------------------------------------------------------------------------ -variable "cluster_name" { - description = "Name of the EKS cluster. Also used as a prefix in names of related resources." - type = string -} - -variable "cluster_version" { - description = "Kubernetes version to use for the EKS cluster." - type = string -} - -variable "enable_irsa" { - description = "Whether to create OpenID Connect Provider for EKS to enable IRSA" - type = bool - default = false -} - - -variable "environment_domain" { - type = string -} - -variable "map_users" { - description = "Additional IAM users to add to the aws-auth configmap. See examples/basic/variables.tf for example format." - type = list(object({ - userarn = string - username = string - groups = list(string) - })) - default = [] -} - - - -variable "environment_namespace" { - type = string -} - -variable "map_roles" { - description = "Additional IAM roles to add to the aws-auth configmap. See examples/basic/variables.tf for example format." - type = list(object({ - rolearn = string - username = string - groups = list(string) - })) - default = [] -} - -variable "map_accounts" { - description = "Additional AWS account numbers to add to the aws-auth configmap. See examples/basic/variables.tf for example format." - type = list(string) - default = [] -} - -variable "root_domain" { - description = "Root domain (route53 zone) for the default cluster ingress." - type = string -} - -variable "subdomains" { - description = "Base domain (route53 zone) for the default cluster ingress" - type = list(string) -} - -variable "subnets" { - description = "A list of subnets to place the EKS cluster and workers within." - type = list(string) -} - -variable "tags" { - description = "A map of tags to add to all resources. Tags added to launch configuration or templates override these values for ASG Tags only." - type = map(string) - default = {} -} - - -variable "vpc_id" { - description = "VPC where the cluster and workers will be deployed." - type = string -} - -variable "worker_group_asg_max_size" { - description = "Max number of nodes on the worker group ASG" - type = number - default = 1 -} - -variable "worker_group_asg_min_size" { - description = "Min number of nodes on the worker group ASG" - type = number - default = 1 -} - -variable "worker_group_instance_type" { - description = "Instance type for the worker group" - type = string - default = null -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/jwt/main.tf b/{{cookiecutter.github_repo_name}}/terraform/components/jwt/main.tf deleted file mode 100644 index d9d94210..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/jwt/main.tf +++ /dev/null @@ -1,22 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: create a Javascript Web Token (JWT) to be added -# to the Open edX build configuration. -#------------------------------------------------------------------------------ -data "aws_eks_cluster" "eks" { - name = var.environment_namespace -} - -data "aws_eks_cluster_auth" "eks" { - name = var.environment_namespace -} - -provider "kubernetes" { - host = data.aws_eks_cluster.eks.endpoint - cluster_ca_certificate = base64decode(data.aws_eks_cluster.eks.certificate_authority[0].data) - token = data.aws_eks_cluster_auth.eks.token -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/jwt/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/components/jwt/versions.tf deleted file mode 100644 index d3d16812..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/jwt/versions.tf +++ /dev/null @@ -1,19 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: create a Javascript Web Token (JWT) to be added -# to the Open edX build configuration. -#------------------------------------------------------------------------------ -terraform { - required_version = "{{ cookiecutter.terraform_required_version }}" - - required_providers { - aws = { - source = "hashicorp/aws" - version = "{{ cookiecutter.terraform_provider_hashicorp_aws_version }}" - } - } -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/kubernetes/main.tf b/{{cookiecutter.github_repo_name}}/terraform/components/kubernetes/main.tf deleted file mode 100644 index be880f0f..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/kubernetes/main.tf +++ /dev/null @@ -1,27 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: create an EKS cluster. -#------------------------------------------------------------------------------ -data "aws_eks_cluster" "eks" { - name = var.environment_namespace -} - -data "aws_eks_cluster_auth" "eks" { - name = var.environment_namespace -} - -provider "kubernetes" { - host = data.aws_eks_cluster.eks.endpoint - cluster_ca_certificate = base64decode(data.aws_eks_cluster.eks.certificate_authority[0].data) - token = data.aws_eks_cluster_auth.eks.token -} - -resource "kubernetes_namespace" "namespace" { - metadata { - name = var.environment_namespace - } -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/kubernetes/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/components/kubernetes/variables.tf deleted file mode 100644 index 470b28e6..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/kubernetes/variables.tf +++ /dev/null @@ -1,24 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: create an EKS cluster. -#------------------------------------------------------------------------------ -variable "environment_namespace" { - description = "kubernetes namespace where to place resources" - type = string -} - -variable "resource_name" { - description = "the full environment-qualified name of this resource." - type = string -} - - -variable "tags" { - description = "collection of all tags to add to this resource. execting the combination of global + environment + resouce tags." - type = map(string) - default = {} -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/mysql/main.tf b/{{cookiecutter.github_repo_name}}/terraform/components/mysql/main.tf deleted file mode 100644 index 46ad69ca..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/mysql/main.tf +++ /dev/null @@ -1,85 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: create an RDS MySQL instance. -#------------------------------------------------------------------------------ -locals { - name = var.identifier - -} - -################################################################################ -# Supporting Resources -################################################################################ - -module "security_group" { - source = "terraform-aws-modules/security-group/aws" - version = "~> 4" - - name = local.name - description = "Allow access to MySQL" - vpc_id = var.vpc_id - - # ingress - ingress_with_cidr_blocks = [ - { - from_port = 3306 - to_port = 3306 - protocol = "tcp" - description = "MySQL access from within VPC" - cidr_blocks = join(",", var.ingress_cidr_blocks) - }, - ] - tags = var.tags -} - - -################################################################################ -# RDS Module -################################################################################ - -module "db" { - source = "git::https://github.com/terraform-aws-modules/terraform-aws-rds.git?ref=v3.0.0" - - identifier = var.identifier - - # All available versions: http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_MySQL.html#MySQL.Concepts.VersionMgmt - engine = var.engine - engine_version = var.engine_version - family = var.family - major_engine_version = var.major_engine_version - instance_class = var.instance_class - - allocated_storage = var.allocated_storage - max_allocated_storage = var.max_allocated_storage - storage_encrypted = var.storage_encrypted - - name = var.name - username = var.username - port = var.port - - create_random_password = var.create_random_password - - multi_az = var.multi_az - subnet_ids = var.subnet_ids - vpc_security_group_ids = [module.security_group.security_group_id] - - maintenance_window = var.maintenance_window - backup_window = var.backup_window - enabled_cloudwatch_logs_exports = var.enabled_cloudwatch_logs_exports - - backup_retention_period = var.backup_retention_period - skip_final_snapshot = var.skip_final_snapshot - deletion_protection = var.deletion_protection - - performance_insights_enabled = var.performance_insights_enabled - performance_insights_retention_period = var.performance_insights_retention_period - create_monitoring_role = var.create_monitoring_role - monitoring_interval = var.monitoring_interval - - parameters = var.parameters - tags = var.tags -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/secrets/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/components/secrets/variables.tf deleted file mode 100644 index cd7e488d..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/secrets/variables.tf +++ /dev/null @@ -1,22 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -#------------------------------------------------------------------------------ -variable "environment_namespace" { - description = "kubernetes namespace where to place resources" - type = string -} - -variable "resource_name" { - description = "the full environment-qualified name of this resource." - type = string -} - - -variable "tags" { - description = "collection of all tags to add to this resource. execting the combination of global + environment + resouce tags." - type = map(string) - default = {} -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/vpc/certificate_manager.tf b/{{cookiecutter.github_repo_name}}/terraform/components/vpc/certificate_manager.tf deleted file mode 100644 index 7f1015ce..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/vpc/certificate_manager.tf +++ /dev/null @@ -1,153 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Lawrence McDaniel -# https://lawrencemcdaniel.com/ -# -# date: Feb-2022 -# -# usage: Add DNS records and tls certs to environment aws_region for ALB. -# Also add certs to us-east-1 for Cloudfront distributions. -# -# we have to add these here, inside of eks_fargate because we -# need to iterate the subdomains, and this is only possible -# within the terragrunt module in which the subdomain -# resources are created. -# -# that is, the following line only works from -# inside eks: -# aws_route53_zone.subdomain[count.index].name -# -# where aws_route53_zone was declared as a resource rather -# than as data -#------------------------------------------------------------------------------ - -#------------------------------------------------------------------------------ -# SSL/TLS certs issued in the AWS region for ALB -#------------------------------------------------------------------------------ -provider "aws" { - alias = "environment_region" - region = var.aws_region -} - -module "acm_root_domain_environment_region" { - source = "terraform-aws-modules/acm/aws" - version = "~> 3.0" - - providers = { - aws = aws.environment_region - } - - domain_name = var.root_domain - zone_id = data.aws_route53_zone.root_domain.id - - subject_alternative_names = [ - "*.${var.root_domain}", - ] - - wait_for_validation = true - tags = var.tags -} - -module "acm_environment_environment_region" { - source = "terraform-aws-modules/acm/aws" - version = "~> 3.0" - - providers = { - aws = aws.environment_region - } - - domain_name = var.environment_domain - zone_id = data.aws_route53_zone.environment_domain.id - - subject_alternative_names = [ - "*.${var.environment_domain}", - ] - - wait_for_validation = true - tags = var.tags -} - -module "acm_subdomains_environment_region" { - source = "terraform-aws-modules/acm/aws" - version = "~> 3.0" - - providers = { - aws = aws.environment_region - } - - count = length(var.subdomains) - domain_name = aws_route53_zone.subdomain[count.index].name - zone_id = aws_route53_zone.subdomain[count.index].id - - subject_alternative_names = [ - "*.${aws_route53_zone.subdomain[count.index].name}", - ] - - wait_for_validation = true - tags = var.tags -} - -#------------------------------------------------------------------------------ -# SSL/TLS certs issued in us-east-1 for Cloudfront -#------------------------------------------------------------------------------ -provider "aws" { - alias = "us-east-1" - region = "us-east-1" -} - -module "acm_root_domain" { - source = "terraform-aws-modules/acm/aws" - version = "~> 3.0" - - providers = { - aws = aws.us-east-1 - } - - domain_name = var.root_domain - zone_id = data.aws_route53_zone.root_domain.id - - subject_alternative_names = [ - "*.${var.root_domain}", - ] - - wait_for_validation = true - tags = var.tags -} - -module "acm_environment_domain" { - source = "terraform-aws-modules/acm/aws" - version = "~> 3.0" - - providers = { - aws = aws.us-east-1 - } - - domain_name = var.environment_domain - zone_id = data.aws_route53_zone.environment_domain.id - - subject_alternative_names = [ - "*.${var.environment_domain}", - ] - - wait_for_validation = true - tags = var.tags -} - -module "acm_subdomains" { - source = "terraform-aws-modules/acm/aws" - version = "~> 3.0" - - providers = { - aws = aws.us-east-1 - } - - count = length(var.subdomains) - domain_name = aws_route53_zone.subdomain[count.index].name - zone_id = aws_route53_zone.subdomain[count.index].id - - subject_alternative_names = [ - "*.${aws_route53_zone.subdomain[count.index].name}", - ] - - wait_for_validation = true - tags = var.tags -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/vpc/route53.tf b/{{cookiecutter.github_repo_name}}/terraform/components/vpc/route53.tf deleted file mode 100644 index 57fbb17c..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/components/vpc/route53.tf +++ /dev/null @@ -1,32 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Lawrence McDaniel -# https://lawrencemcdaniel.com/ -# -# date: Aug-2021 -# -# usage: create a VPC to contain all Open edX backend resources. -#------------------------------------------------------------------------------ - -# un-comment this if the root_domain is managed in route53 -# ----------------------------------------------------------------------------- -data "aws_route53_zone" "root_domain" { - name = var.root_domain -} - -data "aws_route53_zone" "environment_domain" { - name = var.environment_domain -} - -resource "aws_route53_zone" "subdomain" { - count = length(var.subdomains) - name = "${element(var.subdomains, count.index)}.${var.environment_domain}" -} - -resource "aws_route53_record" "subdomain-ns" { - count = length(var.subdomains) - zone_id = data.aws_route53_zone.environment_domain.zone_id - name = "${element(var.subdomains, count.index)}.${var.environment_domain}" - type = "NS" - ttl = "30" - records = aws_route53_zone.subdomain[count.index].name_servers -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/README.md b/{{cookiecutter.github_repo_name}}/terraform/environments/README.md index 315bb13a..0cda2f73 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/README.md +++ b/{{cookiecutter.github_repo_name}}/terraform/environments/README.md @@ -4,9 +4,7 @@ Terraform environments give you the ability to create multiple, distinct AWS VPC The general strategy is that a common set of parameters are defined in [terraform/environments/global.hcl](./global.hcl) that each environment uses, plus, each environment maintains its own set of parameters for environment-specific settings like domain names and resource instances sizes for example. -On an aside, choosing appropriate names for Terragrunt environments was a struggle. the environment named **prod** in this folder was originally named **live** as a means of differentiating it from alternative environments like say, **sandbox**. This was sensible, but it also complicates managing consistent namespaces in AWS and in Kubernetes. We opted to rename this to **prod** since Cookiecutter only creates one single environment for you, and this is where your prod environment resides. Unfortunately, this creates some potential confusion given that the recommended way of creating dev / qa / test environments is to add appropriately named subdomains to prod. - -So, to be clear, creating additional Terragrunt environments might be more separation than you actually require, and add more costs than your budget can bear. Keep in mind that this is probably more easily accomplished simply by adding subdomains to the one VPC that is created based on the settings in [terraform/environments/prod/env.hcl](./prod/env.hcl), as follows: +So, to be clear, creating additional Terragrunt environments might be more separation than you actually require, and add more costs than your budget can bear. Keep in mind that this is probably more easily accomplished simply by adding subdomains to the one VPC that is created based on the settings in [terraform/environments/{{ cookiecutter.environment_name }}/env.hcl](./{{ cookiecutter.environment_name }}/env.hcl), as follows: ``` locals { @@ -26,4 +24,4 @@ The difference between these two methodologies is that the former creates an ent ### Why wouldn't you create an additional Terragrunt environment? -Contrastly, if you are budget conscious and you are otherwise indifferent to how and where your development and qa environments are housed -- provided of course that these are reasonably isolated from your prod environment -- then you would simply add subdomains to [terraform/environments/prod/env.hcl](terraform/environments/prod/env.hcl). +Contrastly, if you are budget conscious and you are otherwise indifferent to how and where your development and qa environments are housed -- provided of course that these are reasonably isolated from your prod environment -- then you would simply add subdomains to [terraform/environments/{{ cookiecutter.environment_name }}/env.hcl](terraform/environments/{{ cookiecutter.environment_name }}/env.hcl). diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/cloudfront/terragrunt.hcl b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/cloudfront/terragrunt.hcl index 9a00f5fd..4a13d325 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/cloudfront/terragrunt.hcl +++ b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/cloudfront/terragrunt.hcl @@ -28,14 +28,14 @@ locals { } dependencies { - paths = ["../s3"] + paths = ["../vpc", "../s3_openedx_storage"] } # Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the # working directory, into a temporary folder, and execute your Terraform commands in that folder. terraform { - source = "../../../components//cloudfront" + source = "../../../modules//cloudfront" } # Include all settings from the root terragrunt.hcl file diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/data-backup-s3/terragrunt.hcl b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/data-backup-s3/terragrunt.hcl deleted file mode 100644 index debe81a1..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/data-backup-s3/terragrunt.hcl +++ /dev/null @@ -1,65 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: create a non-public S3 Bucket to store data backups from any backend -# service. -#------------------------------------------------------------------------------ -locals { - # Automatically load environment-level variables - environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) - global_vars = read_terragrunt_config(find_in_parent_folders("global.hcl")) - - # Extract out common variables for reuse - environment = local.environment_vars.locals.environment - environment_namespace = local.environment_vars.locals.environment_namespace - aws_region = local.global_vars.locals.aws_region - - resource_name = "${local.environment_vars.locals.environment_namespace}-data-backup" - - tags = merge( - local.environment_vars.locals.tags, - local.global_vars.locals.tags, - { Name = "${local.resource_name}" } - ) - -} - -dependencies { - paths = ["../eks", "../vpc"] -} - -dependency "vpc" { - config_path = "../vpc" - - # Configure mock outputs for the `validate` command that are returned when there are no outputs available (e.g the - # module hasn't been applied yet. - mock_outputs_allowed_terraform_commands = ["init", "validate"] - mock_outputs = { - vpc_id = "fake-vpc-id" - public_subnets = ["fake-public-subnet-01", "fake-public-subnet-02"] - public_subnets_cidr_blocks = ["fake-subnet-cidr-block-01", "fake-subnet-cidr-block-01"] - security_group_name_prefix = "fake-group-name-prefix" - } -} - -# Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the -# working directory, into a temporary folder, and execute your Terraform commands in that folder. -terraform { - source = "../../../components//data_backup_s3" -} - -# Include all settings from the root terragrunt.hcl file -include { - path = find_in_parent_folders() -} - -# These are the variables we have to pass in to use the module specified in the terragrunt configuration above -inputs = { - secret_name = "s3-data-backup-${local.environment}" - aws_region = "${local.aws_region}" - resource_name = local.resource_name - tags = local.tags -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/bastion/terragrunt.hcl b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/ec2_bastion/terragrunt.hcl similarity index 93% rename from {{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/bastion/terragrunt.hcl rename to {{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/ec2_bastion/terragrunt.hcl index 110cd667..7b461e2b 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/bastion/terragrunt.hcl +++ b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/ec2_bastion/terragrunt.hcl @@ -33,7 +33,7 @@ locals { dependency "vpc" { config_path = "../vpc" - # Configure mock outputs for the `validate` command that are returned when there are no outputs available (e.g the + # Configure mock outputs for the `validate` and `init` commands that are returned when there are no outputs available (e.g the # module hasn't been applied yet. mock_outputs_allowed_terraform_commands = ["init", "validate"] mock_outputs = { @@ -47,7 +47,7 @@ dependency "vpc" { # Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the # working directory, into a temporary folder, and execute your Terraform commands in that folder. terraform { - source = "../../../components//bastion" + source = "../../../modules//ec2_bastion" } # Include all settings from the root terragrunt.hcl file diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/eks_clb_ec2/README.rst b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/eks_clb_ec2/README.rst deleted file mode 100644 index 2f978414..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/eks_clb_ec2/README.rst +++ /dev/null @@ -1 +0,0 @@ -EKS diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/env.hcl b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/env.hcl index 082f9e1a..ba1d880b 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/env.hcl +++ b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/env.hcl @@ -49,8 +49,8 @@ locals { # # see: https://aws.amazon.com/ec2/instance-types/ #---------------------------------------------------------------------------- - kubernetes_version = {{ cookiecutter.eks_cluster_version }} - eks_worker_group_instance_type = "a1.medium" + kubernetes_version = {{ cookiecutter.kubernetes_cluster_version }} + eks_worker_group_instance_type = "t3.large" eks_worker_group_min_size = 1 eks_worker_group_max_size = 2 eks_worker_group_desired_size = 1 diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/jwt/terragrunt.hcl b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/jwt/terragrunt.hcl deleted file mode 100644 index 0ed7212b..00000000 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/jwt/terragrunt.hcl +++ /dev/null @@ -1,62 +0,0 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: create a Javascript Web Token (JWT) to be added -# to the Open edX build configuration. -#------------------------------------------------------------------------------ -locals { - # Automatically load environment-level variables - environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) - global_vars = read_terragrunt_config(find_in_parent_folders("global.hcl")) - - resource_name = "${local.environment_vars.locals.environment_namespace}" - - tags = merge( - local.environment_vars.locals.tags, - local.global_vars.locals.tags, - { Name = "${local.resource_name}" } - ) - -} - - -dependencies { - paths = ["../eks", "../vpc", "../kubernetes"] -} - -dependency "vpc" { - config_path = "../vpc" - - # Configure mock outputs for the `validate` command that are returned when there are no outputs available (e.g the - # module hasn't been applied yet. - mock_outputs_allowed_terraform_commands = ["init", "validate"] - mock_outputs = { - vpc_id = "fake-vpc-id" - public_subnets = ["fake-public-subnet-01", "fake-public-subnet-02"] - public_subnets_cidr_blocks = ["fake-subnet-cidr-block-01", "fake-subnet-cidr-block-01"] - security_group_name_prefix = "fake-group-name-prefix" - } -} - -# Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the -# working directory, into a temporary folder, and execute your Terraform commands in that folder. - -terraform { - source = "../../../components//jwt" -} - -# Include all settings from the root terragrunt.hcl file -include { - path = find_in_parent_folders() -} - -# These are the variables we have to pass in to use the module specified in the terragrunt configuration above -inputs = { - - resource_name = local.resource_name - tags = local.tags - -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/kubernetes/README.md b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/kubernetes/README.md new file mode 100644 index 00000000..10a24a0f --- /dev/null +++ b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/kubernetes/README.md @@ -0,0 +1 @@ +# Elastic Kubernetes Service diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/kubernetes/terragrunt.hcl b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/kubernetes/terragrunt.hcl index 44d5f30c..0d1f399a 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/kubernetes/terragrunt.hcl +++ b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/kubernetes/terragrunt.hcl @@ -1,46 +1,59 @@ #------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ +# written by: Lawrence McDaniel +# https://lawrencemcdaniel.com # -# date: Aug-2021 +# date: Mar-2022 # -# usage: create an EKS cluster. +# usage: build an EKS with EC2 worker nodes and ALB #------------------------------------------------------------------------------ locals { # Automatically load environment-level variables environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) global_vars = read_terragrunt_config(find_in_parent_folders("global.hcl")) - resource_name = "${local.environment_vars.locals.environment_namespace}" + # Extract out common variables for reuse + env = local.environment_vars.locals.environment + environment_domain = local.environment_vars.locals.environment_domain + environment_namespace = local.environment_vars.locals.environment_namespace + subdomains = local.environment_vars.locals.subdomains + root_domain = local.global_vars.locals.root_domain + platform_name = local.global_vars.locals.platform_name + platform_region = local.global_vars.locals.platform_region + account_id = local.global_vars.locals.account_id + aws_region = local.global_vars.locals.aws_region + + kubernetes_version = local.environment_vars.locals.kubernetes_version + eks_worker_group_instance_type = local.environment_vars.locals.eks_worker_group_instance_type + eks_worker_group_min_size = local.environment_vars.locals.eks_worker_group_min_size + eks_worker_group_max_size = local.environment_vars.locals.eks_worker_group_max_size + eks_worker_group_desired_size = local.environment_vars.locals.eks_worker_group_desired_size tags = merge( local.environment_vars.locals.tags, local.global_vars.locals.tags, - { Name = "${local.resource_name}" } + { Name = "${local.environment_namespace}-eks" } ) - -} - -dependencies { - paths = ["../eks", "../vpc"] } dependency "vpc" { config_path = "../vpc" - # Configure mock outputs for the `validate` command that are returned when there are no outputs available (e.g the + # Configure mock outputs for the `validate` and `init` commands that are returned when there are no outputs available (e.g the # module hasn't been applied yet. mock_outputs_allowed_terraform_commands = ["init", "validate"] mock_outputs = { - vpc_id = "fake-vpc-id" - public_subnets = ["fake-public-subnet-01", "fake-public-subnet-02"] - public_subnets_cidr_blocks = ["fake-subnet-cidr-block-01", "fake-subnet-cidr-block-01"] - security_group_name_prefix = "fake-group-name-prefix" + vpc_id = "fake-vpc-id" + public_subnets = ["fake-public-subnet-01", "fake-public-subnet-02"] + private_subnets = ["fake-private-subnet-01", "fake-private-subnet-02"] + database_subnets = ["fake-database-subnet-01", "fake-database-subnet-02"] } + } +# Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the +# working directory, into a temporary folder, and execute your Terraform commands in that folder. terraform { - source = "../../../components//kubernetes" + source = "../../../modules//kubernetes" } # Include all settings from the root terragrunt.hcl file @@ -50,6 +63,27 @@ include { # These are the variables we have to pass in to use the module specified in the terragrunt configuration above inputs = { - resource_name = local.resource_name - tags = local.tags + aws_region = local.aws_region + environment_domain = local.environment_domain + root_domain = local.root_domain + environment_namespace = local.environment_namespace + subdomains = local.subdomains + private_subnet_ids = dependency.vpc.outputs.private_subnets + public_subnet_ids = dependency.vpc.outputs.public_subnets + vpc_id = dependency.vpc.outputs.vpc_id + kubernetes_cluster_version = local.kubernetes_version + eks_worker_group_instance_type = local.eks_worker_group_instance_type + eks_worker_group_min_size = local.eks_worker_group_min_size + eks_worker_group_max_size = local.eks_worker_group_max_size + eks_worker_group_desired_size = local.eks_worker_group_desired_size + tags = local.tags + map_roles = [] + map_users = [ + { + userarn = "arn:aws:iam::{{ cookiecutter.global_account_id }}:user/ci" + username = "ci" + groups = ["system:masters"] + } + ] + } diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/eks_clb_ec2/terragrunt.hcl b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/kubernetes_ingress_clb/terragrunt.hcl similarity index 57% rename from {{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/eks_clb_ec2/terragrunt.hcl rename to {{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/kubernetes_ingress_clb/terragrunt.hcl index d0f50533..c52e8d67 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/eks_clb_ec2/terragrunt.hcl +++ b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/kubernetes_ingress_clb/terragrunt.hcl @@ -1,10 +1,10 @@ #------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ +# written by: Lawrence McDaniel +# https://lawrencemcdaniel.com # -# date: Aug-2021 +# date: Mar-2022 # -# usage: build an EKS cluster load balancer +# usage: build an EKS with EC2 worker nodes and ALB #------------------------------------------------------------------------------ locals { # Automatically load environment-level variables @@ -12,29 +12,36 @@ locals { global_vars = read_terragrunt_config(find_in_parent_folders("global.hcl")) # Extract out common variables for reuse - platform_name = local.global_vars.locals.platform_name - platform_region = local.global_vars.locals.platform_region - account_id = local.global_vars.locals.account_id env = local.environment_vars.locals.environment environment_domain = local.environment_vars.locals.environment_domain - cluster_name = local.environment_vars.locals.environment_namespace + environment_namespace = local.environment_vars.locals.environment_namespace subdomains = local.environment_vars.locals.subdomains - eks_worker_group_instance_type = local.environment_vars.locals.eks_worker_group_instance_type + root_domain = local.global_vars.locals.root_domain + platform_name = local.global_vars.locals.platform_name + platform_region = local.global_vars.locals.platform_region + account_id = local.global_vars.locals.account_id + aws_region = local.global_vars.locals.aws_region tags = merge( local.environment_vars.locals.tags, local.global_vars.locals.tags, + { Name = "${local.environment_namespace}-eks-ingress" } ) } +dependencies { + paths = ["../vpc", "../kubernetes"] +} + dependency "vpc" { config_path = "../vpc" - # Configure mock outputs for the `validate` command that are returned when there are no outputs available (e.g the + # Configure mock outputs for the `validate` and `init` commands that are returned when there are no outputs available (e.g the # module hasn't been applied yet. mock_outputs_allowed_terraform_commands = ["init", "validate"] mock_outputs = { vpc_id = "fake-vpc-id" + public_subnets = ["fake-public-subnet-01", "fake-public-subnet-02"] private_subnets = ["fake-private-subnet-01", "fake-private-subnet-02"] database_subnets = ["fake-database-subnet-01", "fake-database-subnet-02"] } @@ -44,7 +51,7 @@ dependency "vpc" { # Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the # working directory, into a temporary folder, and execute your Terraform commands in that folder. terraform { - source = "../../../components//eks_clb_ec2" + source = "../../../modules//kubernetes_ingress_clb" } # Include all settings from the root terragrunt.hcl file @@ -54,42 +61,13 @@ include { # These are the variables we have to pass in to use the module specified in the terragrunt configuration above inputs = { + aws_region = local.aws_region + environment_domain = local.environment_domain + root_domain = local.root_domain + environment_namespace = local.environment_namespace subdomains = local.subdomains - cluster_name = "${local.cluster_name}" - cluster_version = "1.21" - enable_irsa = true - - # Subnets - subnets = dependency.vpc.outputs.private_subnets + private_subnet_ids = dependency.vpc.outputs.private_subnets + public_subnet_ids = dependency.vpc.outputs.public_subnets vpc_id = dependency.vpc.outputs.vpc_id - - #worker group - worker_group_asg_max_size = 5 - worker_group_asg_min_size = 1 - worker_group_instance_type = local.eks_worker_group_instance_type - - environment_domain = local.environment_domain - - # TODO: Make this dynamic from list of users / ops user management - map_users = [ - { - userarn = "arn:aws:iam::${local.account_id}:user/ci" - username = "ci" - groups = ["system:masters"] - } - - # ------------------------------------------------------------------------- - # Add more users here, if you'd like. This will give the user the ability - # to connect to the Elastic Kubernetes Cluster via a tool like K9s. - # - # Un-comment this example: - # ------------------------------------------------------------------------- - #{ - # userarn = "arn:aws:iam::${local.account_id}:user/mcdaniel" - # username = "mcdaniel" - # groups = ["system:masters"] - #} - ] - tags = local.tags } diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/secrets/terragrunt.hcl b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/kubernetes_secrets/terragrunt.hcl similarity index 78% rename from {{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/secrets/terragrunt.hcl rename to {{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/kubernetes_secrets/terragrunt.hcl index 3f5ccd1b..7965ba31 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/secrets/terragrunt.hcl +++ b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/kubernetes_secrets/terragrunt.hcl @@ -11,7 +11,8 @@ locals { environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) global_vars = read_terragrunt_config(find_in_parent_folders("global.hcl")) - resource_name = "${local.environment_vars.locals.environment_namespace}" + resource_name = local.environment_vars.locals.environment_namespace + environment_namespace = local.environment_vars.locals.environment_namespace tags = merge( local.environment_vars.locals.tags, @@ -22,13 +23,13 @@ locals { } dependencies { - paths = ["../eks", "../vpc", "../kubernetes"] + paths = ["../vpc", "../kubernetes"] } dependency "vpc" { config_path = "../vpc" - # Configure mock outputs for the `validate` command that are returned when there are no outputs available (e.g the + # Configure mock outputs for the `validate` and `init` commands that are returned when there are no outputs available (e.g the # module hasn't been applied yet. mock_outputs_allowed_terraform_commands = ["init", "validate"] mock_outputs = { @@ -43,7 +44,7 @@ dependency "vpc" { # working directory, into a temporary folder, and execute your Terraform commands in that folder. terraform { - source = "../../../components//secrets" + source = "../../../modules//kubernetes_secrets" } # Include all settings from the root terragrunt.hcl file @@ -54,5 +55,7 @@ include { # These are the variables we have to pass in to use the module specified in the terragrunt configuration above inputs = { resource_name = local.resource_name + environment_namespace = local.environment_namespace + namespace = "openedx" tags = local.tags } diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/mongodb/terragrunt.hcl b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/mongodb/terragrunt.hcl index beb05d90..c486536a 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/mongodb/terragrunt.hcl +++ b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/mongodb/terragrunt.hcl @@ -33,25 +33,52 @@ locals { } dependencies { - paths = ["../vpc", "../kubernetes"] + paths = ["../kubernetes", "../kubernetes_secrets", "../vpc"] } dependency "vpc" { config_path = "../vpc" - # Configure mock outputs for the `validate` command that are returned when there are no outputs available (e.g the + # Configure mock outputs for the `validate` and `init` commands that are returned when there are no outputs available (e.g the # module hasn't been applied yet. - mock_outputs_allowed_terraform_commands = ["validate"] + mock_outputs_allowed_terraform_commands = ["init", "validate"] mock_outputs = { vpc_id = "fake-vpc-id" database_subnets = ["fake-subnetid-01", "fake-subnetid-02"] + vpc_cidr_block = "fake-cidr-block" + } +} + +dependency "kubernetes" { + config_path = "../kubernetes" + + # Configure mock outputs for the `validate` and `init` commands that are returned when there are no outputs available (e.g the + # module hasn't been applied yet. + mock_outputs_allowed_terraform_commands = ["init", "validate"] + mock_outputs = { + cluster_arn = "fake-cluster-arn" + cluster_certificate_authority_data = "fake-cert" + cluster_endpoint = "fake-cluster-endpoint" + cluster_id = "fake-cluster-id" + cluster_oidc_issuer_url = "fake-oidc-issuer-url" + cluster_platform_version = "fake-cluster-version" + cluster_security_group_arn = "fake-security-group-arn" + cluster_security_group_id = "fake-security-group-id" + cluster_status = "fake-cluster-status" + cluster_version = "fake-cluster-version" + eks_managed_node_groups = "fake-managed-node-group" + fargate_profiles = "fake-fargate-profile" + node_security_group_arn = "fake-security-group-arn" + node_security_group_id = "fake-security-group-id" + oidc_provider = "fake-oidc-provider" + oidc_provider_arn = "fake-provider-arn" } } # Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the # working directory, into a temporary folder, and execute your Terraform commands in that folder. terraform { - source = "../../../components//mongodb" + source = "../../../modules//mongodb" } # Include all settings from the root terragrunt.hcl file diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/mysql/terragrunt.hcl b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/mysql/terragrunt.hcl index 18f2f80c..a8b82d04 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/mysql/terragrunt.hcl +++ b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/mysql/terragrunt.hcl @@ -12,6 +12,7 @@ locals { global_vars = read_terragrunt_config(find_in_parent_folders("global.hcl")) resource_name = "${local.environment_vars.locals.environment_namespace}" + identifier = "${local.environment_vars.locals.environment}" mysql_instance_class = local.environment_vars.locals.mysql_instance_class tags = merge( @@ -23,25 +24,52 @@ locals { } dependencies { - paths = ["../vpc", "../kubernetes"] + paths = ["../kubernetes", "../kubernetes_secrets", "../vpc"] } dependency "vpc" { config_path = "../vpc" - # Configure mock outputs for the `validate` command that are returned when there are no outputs available (e.g the + # Configure mock outputs for the `validate` and `init` commands that are returned when there are no outputs available (e.g the # module hasn't been applied yet. - mock_outputs_allowed_terraform_commands = ["validate"] + mock_outputs_allowed_terraform_commands = ["init", "validate"] mock_outputs = { vpc_id = "fake-vpc-id" database_subnets = ["fake-subnetid-01", "fake-subnetid-02"] + vpc_cidr_block = "fake-cidr-block" + } +} + +dependency "kubernetes" { + config_path = "../kubernetes" + + # Configure mock outputs for the `validate` and `init` commands that are returned when there are no outputs available (e.g the + # module hasn't been applied yet. + mock_outputs_allowed_terraform_commands = ["init", "validate"] + mock_outputs = { + cluster_arn = "fake-cluster-arn" + cluster_certificate_authority_data = "fake-cert" + cluster_endpoint = "fake-cluster-endpoint" + cluster_id = "fake-cluster-id" + cluster_oidc_issuer_url = "fake-oidc-issuer-url" + cluster_platform_version = "fake-cluster-version" + cluster_security_group_arn = "fake-security-group-arn" + cluster_security_group_id = "fake-security-group-id" + cluster_status = "fake-cluster-status" + cluster_version = "fake-cluster-version" + eks_managed_node_groups = "fake-managed-node-group" + fargate_profiles = "fake-fargate-profile" + node_security_group_arn = "fake-security-group-arn" + node_security_group_id = "fake-security-group-id" + oidc_provider = "fake-oidc-provider" + oidc_provider_arn = "fake-provider-arn" } } # Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the # working directory, into a temporary folder, and execute your Terraform commands in that folder. terraform { - source = "../../../components//mysql" + source = "../../../modules//mysql" } # Include all settings from the root terragrunt.hcl file @@ -54,10 +82,10 @@ inputs = { # AWS RDS instance identifying information resource_name = local.resource_name tags = local.tags - identifier = "${local.resource_name}" # database identifying information name = "openedx" + identifier = local.identifier username = "{{ cookiecutter.mysql_username }}" create_random_password = {{ cookiecutter.mysql_create_random_password }} iam_database_authentication_enabled = {{ cookiecutter.mysql_iam_database_authentication_enabled }} @@ -82,6 +110,15 @@ inputs = { # db server size instance_class = local.mysql_instance_class allocated_storage = {{ cookiecutter.mysql_allocated_storage }} + max_allocated_storage = 0 + storage_encrypted = true + multi_az = false + enabled_cloudwatch_logs_exports = [] + performance_insights_enabled = false + performance_insights_retention_period = 7 + create_monitoring_role = false + monitoring_interval = 0 + create_db_subnet_group = false # backups and maintenance maintenance_window = "{{ cookiecutter.mysql_maintenance_window }}" @@ -90,6 +127,7 @@ inputs = { deletion_protection = {{ cookiecutter.mysql_deletion_protection }} skip_final_snapshot = {{ cookiecutter.mysql_skip_final_snapshot }} + # network configuration subnet_ids = dependency.vpc.outputs.database_subnets vpc_id = dependency.vpc.outputs.vpc_id diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/redis/terragrunt.hcl b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/redis/terragrunt.hcl index 41aa8dc8..975014f2 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/redis/terragrunt.hcl +++ b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/redis/terragrunt.hcl @@ -22,22 +22,50 @@ locals { } terraform { - source = "../../../components//redis" + source = "../../../modules//redis" } dependencies { - paths = ["../vpc", "../kubernetes"] + paths = ["../kubernetes", "../kubernetes_secrets", "../vpc"] } dependency "vpc" { config_path = "../vpc" - # Configure mock outputs for the `validate` command that are returned when there are no outputs available (e.g the + # Configure mock outputs for the `validate` and `init` commands that are returned when there are no outputs available (e.g the # module hasn't been applied yet. - mock_outputs_allowed_terraform_commands = ["validate"] + mock_outputs_allowed_terraform_commands = ["init", "validate"] mock_outputs = { vpc_id = "fake-vpc-id" database_subnets = ["fake-subnetid-01", "fake-subnetid-02"] + elasticache_subnets = ["fake-elasticache-subnet-01", "fake-elasticache-subnet-02"] + vpc_cidr_block = "fake-cidr-block" + } +} + +dependency "kubernetes" { + config_path = "../kubernetes" + + # Configure mock outputs for the `validate` and `init` commands that are returned when there are no outputs available (e.g the + # module hasn't been applied yet. + mock_outputs_allowed_terraform_commands = ["init", "validate"] + mock_outputs = { + cluster_arn = "fake-cluster-arn" + cluster_certificate_authority_data = "fake-cert" + cluster_endpoint = "fake-cluster-endpoint" + cluster_id = "fake-cluster-id" + cluster_oidc_issuer_url = "fake-oidc-issuer-url" + cluster_platform_version = "fake-cluster-version" + cluster_security_group_arn = "fake-security-group-arn" + cluster_security_group_id = "fake-security-group-id" + cluster_status = "fake-cluster-status" + cluster_version = "fake-cluster-version" + eks_managed_node_groups = "fake-managed-node-group" + fargate_profiles = "fake-fargate-profile" + node_security_group_arn = "fake-security-group-arn" + node_security_group_id = "fake-security-group-id" + oidc_provider = "fake-oidc-provider" + oidc_provider_arn = "fake-provider-arn" } } @@ -60,7 +88,7 @@ inputs = { # cache engine configuration engine = "redis" engine_version = "{{ cookiecutter.redis_engine_version }}" - number_cache_clusters = {{ cookiecutter.redis_number_cache_clusters }} + num_cache_clusters = {{ cookiecutter.redis_num_cache_clusters }} port = {{ cookiecutter.redis_port }} family = "{{ cookiecutter.redis_family }}" node_type = local.redis_node_type diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/s3/terragrunt.hcl b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/s3_openedx_storage/terragrunt.hcl similarity index 60% rename from {{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/s3/terragrunt.hcl rename to {{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/s3_openedx_storage/terragrunt.hcl index 8805bf14..ca7c07da 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/s3/terragrunt.hcl +++ b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/s3_openedx_storage/terragrunt.hcl @@ -26,13 +26,13 @@ locals { } dependencies { - paths = ["../eks", "../vpc"] + paths = ["../kubernetes", "../kubernetes_secrets", "../vpc"] } dependency "vpc" { config_path = "../vpc" - # Configure mock outputs for the `validate` command that are returned when there are no outputs available (e.g the + # Configure mock outputs for the `validate` and `init` commands that are returned when there are no outputs available (e.g the # module hasn't been applied yet. mock_outputs_allowed_terraform_commands = ["init", "validate"] mock_outputs = { @@ -43,10 +43,36 @@ dependency "vpc" { } } +dependency "kubernetes" { + config_path = "../kubernetes" + + # Configure mock outputs for the `validate` and `init` commands that are returned when there are no outputs available (e.g the + # module hasn't been applied yet. + mock_outputs_allowed_terraform_commands = ["init", "validate"] + mock_outputs = { + cluster_arn = "fake-cluster-arn" + cluster_certificate_authority_data = "fake-cert" + cluster_endpoint = "fake-cluster-endpoint" + cluster_id = "fake-cluster-id" + cluster_oidc_issuer_url = "fake-oidc-issuer-url" + cluster_platform_version = "fake-cluster-version" + cluster_security_group_arn = "fake-security-group-arn" + cluster_security_group_id = "fake-security-group-id" + cluster_status = "fake-cluster-status" + cluster_version = "fake-cluster-version" + eks_managed_node_groups = "fake-managed-node-group" + fargate_profiles = "fake-fargate-profile" + node_security_group_arn = "fake-security-group-arn" + node_security_group_id = "fake-security-group-id" + oidc_provider = "fake-oidc-provider" + oidc_provider_arn = "fake-provider-arn" + } +} + # Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the # working directory, into a temporary folder, and execute your Terraform commands in that folder. terraform { - source = "../../../components//s3" + source = "../../../modules//s3_openedx_storage" } # Include all settings from the root terragrunt.hcl file diff --git a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/vpc/terragrunt.hcl b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/vpc/terragrunt.hcl index d6a365f7..042fe8ec 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/vpc/terragrunt.hcl +++ b/{{cookiecutter.github_repo_name}}/terraform/environments/{{cookiecutter.environment_name}}/vpc/terragrunt.hcl @@ -30,7 +30,7 @@ locals { # working directory, into a temporary folder, and execute your Terraform commands in that folder. terraform { - source = "../../../components//vpc" + source = "../../../modules//vpc" } # Include all settings from the root terragrunt.hcl file diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/README.md b/{{cookiecutter.github_repo_name}}/terraform/modules/README.md similarity index 77% rename from {{cookiecutter.github_repo_name}}/terraform/components/README.md rename to {{cookiecutter.github_repo_name}}/terraform/modules/README.md index d15762dc..93c39fd5 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/README.md +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/README.md @@ -1,7 +1,7 @@ -## Terraform Components +## Terraform Modules These are logical representations of actual AWS resources (ie services) that you will need in order to horizontally scale a Tutor installation of Open edX. Each component is a complete replacement to its local Tutor-based equivalent. That is, contrastly, simply installing Open edX with Tutor and then accepting all of its questionnaire default responses will result in Tutor implementing Docker containers for all of these services (MySQL, Mongo, Redis, etc.), all of which will run locally on the AWS EC2 instance on which you installed Tutor. Since each of these represent AWS' premium service offering for each respective service (MySQL, MongoDB, Redis, etc), there are more options available to you. For example, each of these services can be independently sized. You can specifiy maintenance windows for automated upgrades, backup time windows and so forth. -Note that **you do not execute any of these Terraform scripts directly**. Quite the contrary, each of these components is wired to its Terragrunt counterpart located in [terraform/environments/prod](terraform/environments/prod) and is called by Terragrunt. +Note that **you do not execute any of these Terraform scripts directly**. Quite the contrary, each of these modules is wired to its Terragrunt counterpart located in [terraform/environments/{{ cookiecutter.environment_name }}](terraform/environments/{{ cookiecutter.environment_name }}) and is called by Terragrunt. diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/cloudfront/certificate_manager.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/cloudfront/certificate_manager.tf new file mode 100644 index 00000000..5fdb37db --- /dev/null +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/cloudfront/certificate_manager.tf @@ -0,0 +1,59 @@ +#------------------------------------------------------------------------------ +# written by: Lawrence McDaniel +# https://lawrencemcdaniel.com/ +# +# date: Feb-2022 +# +# usage: Add DNS records and tls certs to environment aws_region for ALB. +# Also add certs to us-east-1 for Cloudfront distributions. +# +# we have to add these here, inside of eks_fargate because we +# need to iterate the subdomains, and this is only possible +# within the terragrunt module in which the subdomain +# resources are created. +# +# that is, the following line only works from +# inside eks: +# aws_route53_zone.subdomain[count.index].name +# +# where aws_route53_zone was declared as a resource rather +# than as data +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# SSL/TLS certs issued in the AWS region for ALB +#------------------------------------------------------------------------------ +provider "aws" { + alias = "environment_region" + region = var.aws_region +} + +#------------------------------------------------------------------------------ +# SSL/TLS certs issued in us-east-1 for Cloudfront +#------------------------------------------------------------------------------ + +module "acm_environment_domain" { + source = "terraform-aws-modules/acm/aws" + version = "{{ cookiecutter.terraform_aws_modules_acm }}" + + providers = { + aws = aws.us-east-1 + } + + domain_name = var.environment_domain + zone_id = data.aws_route53_zone.environment_domain.id + + subject_alternative_names = [ + "*.${var.environment_domain}", + ] + + wait_for_validation = true + + # adding the Usage tag as a way to differentiate this cert from the one created by + # the eks clb ingress, of which we have no control. + tags = merge( + var.tags, + { Usage = "Cloudfront" } + ) + +} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/cloudfront/main.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/cloudfront/main.tf similarity index 93% rename from {{cookiecutter.github_repo_name}}/terraform/components/cloudfront/main.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/cloudfront/main.tf index 7232b2db..167f8ccd 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/cloudfront/main.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/cloudfront/main.tf @@ -33,9 +33,10 @@ data "aws_route53_zone" "environment_domain" { # see eks_ec2/acm.tf or eks_fargate/acm.tf for creation of this certificate # as well as the definition for the provider "aws.us-east-1" data "aws_acm_certificate" "environment_domain" { - domain = var.environment_domain - statuses = ["ISSUED"] - provider = "aws.us-east-1" + domain = var.environment_domain + statuses = ["ISSUED"] + provider = aws.us-east-1 + depends_on = [module.acm_environment_domain] } data "aws_s3_bucket" "environment_domain" { @@ -59,7 +60,7 @@ resource "aws_route53_record" "cdn_environment_domain" { module "cdn_environment_domain" { source = "terraform-aws-modules/cloudfront/aws" - version = "~> 2" + version = "{{cookiecutter.terraform_aws_modules_cloudfront}}" aliases = [local.cdn_name] diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/cloudfront/outputs.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/cloudfront/outputs.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/cloudfront/outputs.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/cloudfront/outputs.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/cloudfront/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/cloudfront/variables.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/cloudfront/variables.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/cloudfront/variables.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/cloudfront/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/cloudfront/versions.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/cloudfront/versions.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/cloudfront/versions.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/bastion/main.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/ec2_bastion/main.tf similarity index 91% rename from {{cookiecutter.github_repo_name}}/terraform/components/bastion/main.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/ec2_bastion/main.tf index f1f4dd2c..f0883cf9 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/bastion/main.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/ec2_bastion/main.tf @@ -40,11 +40,11 @@ data "aws_key_pair" "common_key" { resource "aws_security_group" "sg_bastion" { name_prefix = "${var.environment_namespace}-bastion" - description = "Public ssh access" + description = "openedx_devops: Public ssh access" vpc_id = var.vpc_id ingress { - description = "public ssh from anywhere" + description = "openedx_devops: public ssh from anywhere" from_port = 22 to_port = 22 protocol = "tcp" @@ -52,6 +52,7 @@ resource "aws_security_group" "sg_bastion" { } egress { + description = "openedx_devops: public ssh out to anywhere" from_port = 0 to_port = 0 protocol = "-1" diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/bastion/outputs.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/ec2_bastion/outputs.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/bastion/outputs.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/ec2_bastion/outputs.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/bastion/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/ec2_bastion/variables.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/bastion/variables.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/ec2_bastion/variables.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/bastion/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/ec2_bastion/versions.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/bastion/versions.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/ec2_bastion/versions.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/README.rst b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/README.rst new file mode 100644 index 00000000..a444c24d --- /dev/null +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/README.rst @@ -0,0 +1,43 @@ +Amazon Elastic Kubernetes Service (EKS) +======================================= + +Implements a `Kubernetes Cluster `_ via `AWS Elastic Kubernetes Service (EKS) `_. A Kubernetes cluster is a set of nodes that run containerized applications that are grouped in pods and organized with namespaces. Containerizing an application into a Docker container means packaging that app with its dependences and its required services into a single binary run-time file that can be downloaded directly from the Docker registry. +Our Kubernetes Cluster resides inside the VPC on a private subnet, meaning that it is generally not visible to the public. In order to be able to receive traffic from the outside world we implement `Kubernetes Ingress Controllers `_ which in turn implement a `Kubernetes Ingress `_ +for both an `AWS Application Load Balancer `_ as well as our `Nginx proxy server `_. + +Implementation Strategy +----------------------- + +Our goal is to, as much as possible, implement a plain vanilla Kubernetes Cluster that generally uses all default configuration values and that includes EC2 as well as Fargate compute nodes. + +This module uses the latest version of the community-supported `AWS EKS Terraform module `_ to create a fully configured Kubernetes Cluster within the custom VPC. +AWS EKS Terraform module is widely supported and adopted, with more than 250 open source code contributers, and more than 10 million downloads from the Terraform registry as of March, 2022. + +How it works +------------ + +Amazon Elastic Kubernetes Service (Amazon EKS) is a managed container service to run and scale Kubernetes applications in the cloud. It is a managed service, meaning that AWS is responsible for up-time, and they apply periodic system updates and security patches automatically. + +.. image:: doc/diagram-eks.png + :width: 100% + :alt: EKS Diagram + + +AWS Fargate Serverless compute for containers +--------------------------------------------- + +AWS Fargate is a serverless, pay-as-you-go computing alternative to traditional EC2 instance-based computing nodes. It is compatible with both `Amazon Elastic Container Service (ECS) `_ and `Amazon Elastic Kubernetes Service (EKS) `_. +There are two distinct benefits to using Fargate instead of EC2 instances. First is cost. Similar to AWS Lambda, you only pay for the compute cycles that you consume. Most Open edX installations provision server infrastructure based on peak load estimates, which in point of fact only occur occasionally, during isolated events like approaching homework due dates, mid-term exams and so on. This in turn leads to EC2 instances being under-utilized most of the time. +Second, related, is scaling. Fargate can absorb whatever workload you send to it, meaning that during peak usage periods of your Open edX platform you won't need to worry about provisioning additional EC2 server capacity. + + +- **Running at scale**. Use Fargate with Amazon ECS or Amazon EKS to easily run and scale your containerized data processing workloads. +- **Optimize Costs**. With AWS Fargate there are no upfront expenses, pay for only the resources used. Further optimize with `Compute Savings Plans `_ and `Fargate Spot `_, then use `Graviton2 `_ powered Fargate for up to 40% price performance improvements. +- Only pay for what you use. Fargate scales the compute to closely match your specified resource requirements. With Fargate, there is no over-provisioning and paying for additional servers. + +How it works +~~~~~~~~~~~~ + +.. image:: doc/diagram-fargate.png + :width: 100% + :alt: Fargate Diagram diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/aws-vpc-eks.png b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/aws-vpc-eks.png new file mode 100644 index 00000000..74e1bf8f Binary files /dev/null and b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/aws-vpc-eks.png differ diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/aws_eks_fargate.png b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/aws_eks_fargate.png new file mode 100644 index 00000000..5f215df5 Binary files /dev/null and b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/aws_eks_fargate.png differ diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/diagram-eks.png b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/diagram-eks.png new file mode 100644 index 00000000..0f791640 Binary files /dev/null and b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/diagram-eks.png differ diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/diagram-fargate.png b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/diagram-fargate.png new file mode 100644 index 00000000..b9690401 Binary files /dev/null and b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/diagram-fargate.png differ diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/node_group-diagram.jpeg b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/node_group-diagram.jpeg new file mode 100644 index 00000000..9219b976 Binary files /dev/null and b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/node_group-diagram.jpeg differ diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/node_security_group_additional_rules.png b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/node_security_group_additional_rules.png new file mode 100644 index 00000000..3bc93e56 Binary files /dev/null and b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/doc/node_security_group_additional_rules.png differ diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/kubernetes.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/kubernetes.tf new file mode 100644 index 00000000..67cda68a --- /dev/null +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/kubernetes.tf @@ -0,0 +1,22 @@ +#------------------------------------------------------------------------------ +# written by: Lawrence McDaniel +# https://lawrencemcdaniel.com/ +# +# date: Mar-2022 +# +# usage: declare a kubernetes provider so that terraform +# can communicate with the kubernetes api. +#------------------------------------------------------------------------------ +data "aws_eks_cluster" "cluster" { + name = module.eks.cluster_id +} + +data "aws_eks_cluster_auth" "cluster" { + name = module.eks.cluster_id +} + +provider "kubernetes" { + host = data.aws_eks_cluster.cluster.endpoint + cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data) + token = data.aws_eks_cluster_auth.cluster.token +} diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/main.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/main.tf new file mode 100644 index 00000000..1591fca1 --- /dev/null +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/main.tf @@ -0,0 +1,96 @@ +#------------------------------------------------------------------------------ +# written by: Lawrence McDaniel +# https://lawrencemcdaniel.com/ +# +# date: Mar-2022 +# +# usage: create an EKS cluster with one managed node group for EC2 +# plus a Fargate profile for serverless computing. +# +# Technical documentation: +# - https://docs.aws.amazon.com/kubernetes +# - https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/ +# +#------------------------------------------------------------------------------ +locals { + + # see: https://github.com/terraform-aws-modules/terraform-aws-eks/issues/1744 + # sepehrmavedati commented on Jan 9 + kubeconfig = "~/.kube/config" + current_auth_configmap = yamldecode(module.eks.aws_auth_configmap_yaml) + map_users = var.map_users + map_roles = var.map_roles + updated_auth_configmap_data = { + data = { + mapRoles = yamlencode( + distinct(concat( + yamldecode(local.current_auth_configmap.data.mapRoles), local.map_roles, ) + )) + mapUsers = yamlencode(local.map_users) + } + } +} + +module "eks" { + source = "terraform-aws-modules/eks/aws" + version = "{{ cookiecutter.terraform_aws_modules_eks }}" + cluster_name = var.environment_namespace + cluster_version = var.kubernetes_cluster_version + cluster_endpoint_private_access = true + cluster_endpoint_public_access = true + enable_irsa = true + vpc_id = var.vpc_id + subnet_ids = var.private_subnet_ids + tags = var.tags + + node_security_group_additional_rules = { + ingress_self_all = { + description = "openedx_devops: Node to node all ports/protocols" + protocol = "-1" + from_port = 0 + to_port = 0 + type = "ingress" + self = true + } + port_8443 = { + description = "openedx_devops: open port 8443 to vpc" + protocol = "-1" + from_port = 8443 + to_port = 8443 + type = "ingress" + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + } + egress_all = { + description = "openedx_devops: Node all egress" + protocol = "-1" + from_port = 0 + to_port = 0 + type = "egress" + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + } + } + + eks_managed_node_groups = { + default = { + min_size = var.eks_worker_group_min_size + max_size = var.eks_worker_group_max_size + desired_size = var.eks_worker_group_desired_size + instance_types = [var.eks_worker_group_instance_type] + tags = var.tags + } + } + +} + +#------------------------------------------------------------------------------ +# Tutor deploys into this namespace, bc of a namesapce command-line argument +# that we pass inside of GitHub Actions deploy workflow +#------------------------------------------------------------------------------ +resource "kubernetes_namespace" "openedx" { + metadata { + name = "openedx" + } + depends_on = [module.eks] +} diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/outputs.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/outputs.tf new file mode 100644 index 00000000..b65597ac --- /dev/null +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/outputs.tf @@ -0,0 +1,185 @@ +#------------------------------------------------------------------------------ +# written by: Lawrence McDaniel +# https://lawrencemcdaniel.com/ +# +# date: Mar-2022 +# +# usage: create an EKS cluster +#------------------------------------------------------------------------------ + +################################################################################ +# Cluster +################################################################################ + +output "cluster_arn" { + description = "The Amazon Resource Name (ARN) of the cluster" + value = module.eks.cluster_arn +} + +output "cluster_certificate_authority_data" { + description = "Base64 encoded certificate data required to communicate with the cluster" + value = module.eks.cluster_certificate_authority_data +} + +output "cluster_endpoint" { + description = "Endpoint for your Kubernetes API server" + value = module.eks.cluster_endpoint +} + +output "cluster_id" { + description = "The name/id of the EKS cluster. Will block on cluster creation until the cluster is really ready" + value = module.eks.cluster_id +} + +output "cluster_oidc_issuer_url" { + description = "The URL on the EKS cluster for the OpenID Connect identity provider" + value = module.eks.cluster_oidc_issuer_url +} + +output "cluster_platform_version" { + description = "Platform version for the cluster" + value = module.eks.cluster_platform_version +} + +output "cluster_status" { + description = "Status of the EKS cluster. One of `CREATING`, `ACTIVE`, `DELETING`, `FAILED`" + value = module.eks.cluster_status +} + +output "cluster_primary_security_group_id" { + description = "Cluster security group that was created by Amazon EKS for the cluster. Managed node groups use this security group for control-plane-to-data-plane communication. Referred to as 'Cluster security group' in the EKS console" + value = module.eks.cluster_primary_security_group_id +} + +################################################################################ +# Security Group +################################################################################ + +output "cluster_security_group_arn" { + description = "Amazon Resource Name (ARN) of the cluster security group" + value = module.eks.cluster_security_group_arn +} + +output "cluster_security_group_id" { + description = "ID of the cluster security group" + value = module.eks.cluster_security_group_id +} + +################################################################################ +# Node Security Group +################################################################################ + +output "node_security_group_arn" { + description = "Amazon Resource Name (ARN) of the node shared security group" + value = module.eks.node_security_group_arn +} + +output "node_security_group_id" { + description = "ID of the node shared security group" + value = module.eks.node_security_group_id +} + +################################################################################ +# IRSA +################################################################################ + +output "oidc_provider" { + description = "The OpenID Connect identity provider (issuer URL without leading `https://`)" + value = module.eks.oidc_provider +} + +output "oidc_provider_arn" { + description = "The ARN of the OIDC Provider if `enable_irsa = true`" + value = module.eks.oidc_provider_arn +} + +################################################################################ +# IAM Role +################################################################################ + +output "cluster_iam_role_name" { + description = "IAM role name of the EKS cluster" + value = module.eks.cluster_iam_role_name +} + +output "cluster_iam_role_arn" { + description = "IAM role ARN of the EKS cluster" + value = module.eks.cluster_iam_role_arn +} + +output "cluster_iam_role_unique_id" { + description = "Stable and unique string identifying the IAM role" + value = module.eks.cluster_iam_role_unique_id +} + +################################################################################ +# EKS Addons +################################################################################ + +output "cluster_addons" { + description = "Map of attribute maps for all EKS cluster addons enabled" + value = module.eks.cluster_addons +} + +################################################################################ +# EKS Identity Provider +################################################################################ + +output "cluster_identity_providers" { + description = "Map of attribute maps for all EKS identity providers enabled" + value = module.eks.cluster_identity_providers +} + +################################################################################ +# CloudWatch Log Group +################################################################################ + +output "cloudwatch_log_group_name" { + description = "Name of cloudwatch log group created" + value = module.eks.cloudwatch_log_group_name +} + +output "cloudwatch_log_group_arn" { + description = "Arn of cloudwatch log group created" + value = module.eks.cloudwatch_log_group_arn +} + +################################################################################ +# Fargate Profile +################################################################################ + +output "fargate_profiles" { + description = "Map of attribute maps for all EKS Fargate Profiles created" + value = module.eks.fargate_profiles +} + +################################################################################ +# EKS Managed Node Group +################################################################################ + +output "eks_managed_node_groups" { + description = "Map of attribute maps for all EKS managed node groups created" + value = module.eks.eks_managed_node_groups +} + +################################################################################ +# Self Managed Node Group +################################################################################ + +output "self_managed_node_groups" { + description = "Map of attribute maps for all self managed node groups created" + value = module.eks.self_managed_node_groups +} + +################################################################################ +# Additional +################################################################################ + +output "aws_auth_configmap_yaml" { + description = "Formatted yaml output for base aws-auth configmap containing roles used in cluster node groups/fargate profiles" + value = module.eks.aws_auth_configmap_yaml +} + +################################################################################ +# ELB +################################################################################ diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/variables.tf new file mode 100644 index 00000000..a828824c --- /dev/null +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/variables.tf @@ -0,0 +1,86 @@ +#------------------------------------------------------------------------------ +# written by: Lawrence McDaniel +# https://lawrencemcdaniel.com/ +# +# date: Mar-2022 +# +# usage: create an EKS cluster +#------------------------------------------------------------------------------ +variable "root_domain" { + type = string +} + +variable "environment_domain" { + type = string +} + +variable "subdomains" { + type = list(string) +} + +variable "environment_namespace" { + type = string +} + +variable "aws_region" { + type = string +} + +variable "vpc_id" { + type = string +} + +variable "private_subnet_ids" { + type = list(string) +} + +variable "tags" { + description = "A map of tags to add to all resources. Tags added to launch configuration or templates override these values for ASG Tags only." + type = map(string) + default = {} +} + +variable "enable_irsa" { + type = bool + default = true +} + +variable "kubernetes_cluster_version" { + type = string +} + +variable "eks_worker_group_min_size" { + type = number +} + +variable "eks_worker_group_max_size" { + type = number +} + +variable "eks_worker_group_desired_size" { + type = number +} + +variable "eks_worker_group_instance_type" { + type = string +} + +variable "map_users" { + description = "Additional IAM users to add to the aws-auth configmap." + type = list(object({ + userarn = string + username = string + groups = list(string) + })) + default = [] +} + +variable "map_roles" { + description = "Additional IAM roles to add to the aws-auth configmap." + type = list(object({ + userarn = string + username = string + groups = list(string) + })) + default = [] +} diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/versions.tf new file mode 100644 index 00000000..c631305f --- /dev/null +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes/versions.tf @@ -0,0 +1,18 @@ +#------------------------------------------------------------------------------ +# written by: Lawrence McDaniel +# https://lawrencemcdaniel.com/ +# +# date: Mar-2022 +# +# usage: create an EKS cluster +#------------------------------------------------------------------------------ +terraform { + required_version = "{{ cookiecutter.terraform_required_version }}" + + required_providers { + aws = "{{ cookiecutter.terraform_provider_hashicorp_aws_version }}" + local = "{{ cookiecutter.terraform_provider_hashicorp_local_version }}" + random = "{{ cookiecutter.terraform_provider_hashicorp_random_version }}" + kubernetes = "{{ cookiecutter.terraform_provider_kubernetes_version }}" + } +} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/README.md b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/README.md similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/README.md rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/README.md diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/acm.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/acm.tf new file mode 100644 index 00000000..26931f61 --- /dev/null +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/acm.tf @@ -0,0 +1,27 @@ +#------------------------------------------------------------------------------ +# written by: Lawrence McDaniel +# https://lawrencemcdaniel.com/ +# +# date: Feb-2022 +# +# usage: Add tls certs to us-east-1 for Cloudfront distributions. +# +# we have to add these here, inside of eks because we +# need to iterate the subdomains, and this is only possible +# within the terragrunt module in which the subdomain +# resources are created. +# +# that is, the following line only works from +# inside eks: +# aws_route53_zone.subdomain[count.index].name +# +# where aws_route53_zone was declared as a resource rather +# than as data +#------------------------------------------------------------------------------ + +# FIX NOTE: do we even need this for anything? + +provider "aws" { + alias = "us-east-1" + region = "us-east-1" +} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/cert-manager-values.yaml.tpl b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/cert-manager-values.yaml.tpl similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/cert-manager-values.yaml.tpl rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/cert-manager-values.yaml.tpl diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/cert-manager.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/cert-manager.tf similarity index 83% rename from {{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/cert-manager.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/cert-manager.tf index 607a3ecd..2c473cc4 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/cert-manager.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/cert-manager.tf @@ -10,8 +10,8 @@ module "cert_manager_irsa" { source = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc" version = "~> 4.1" create_role = true - role_name = "${local.name}-cert_manager-irsa" - provider_url = replace(module.eks.cluster_oidc_issuer_url, "https://", "") + role_name = "${var.environment_namespace}-cert_manager-irsa" + provider_url = replace(data.aws_eks_cluster.eks.identity[0].oidc[0].issuer, "https://", "") role_policy_arns = [aws_iam_policy.cert_manager_policy.arn] oidc_fully_qualified_subjects = ["system:serviceaccount:cert-manager:cert-manager"] } @@ -36,9 +36,9 @@ resource "helm_release" "cert-manager" { } resource "aws_iam_policy" "cert_manager_policy" { - name = "${local.name}-cert-manager-policy" + name = "${var.environment_namespace}-cert-manager-policy" path = "/" - description = "Policy, which allows CertManager to create Route53 records" + description = "openedx_devops: Policy, which allows CertManager to create Route53 records" policy = jsonencode({ "Version" : "2012-10-17", diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/ingress.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/ingress.tf similarity index 94% rename from {{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/ingress.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/ingress.tf index eb95f6f3..e44dfff3 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/ingress.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/ingress.tf @@ -50,7 +50,7 @@ resource "aws_route53_record" "ingress_domains_wildcard" { type = "A" alias { - name = data.kubernetes_service.ingress_nginx_controller.load_balancer_ingress.0.hostname + name = data.kubernetes_service.ingress_nginx_controller.status.0.load_balancer.0.ingress.0.hostname zone_id = data.aws_elb_hosted_zone_id.main.id evaluate_target_health = true } @@ -63,7 +63,7 @@ resource "aws_route53_record" "ingress_domains_naked" { type = "A" alias { - name = data.kubernetes_service.ingress_nginx_controller.load_balancer_ingress.0.hostname + name = data.kubernetes_service.ingress_nginx_controller.status.0.load_balancer.0.ingress.0.hostname zone_id = data.aws_elb_hosted_zone_id.main.id evaluate_target_health = true } diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/main.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/main.tf new file mode 100644 index 00000000..f3b806fa --- /dev/null +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/main.tf @@ -0,0 +1,72 @@ +#------------------------------------------------------------------------------ +# written by: Miguel Afonso +# https://www.linkedin.com/in/mmafonso/ +# +# date: Aug-2021 +# +# usage: build an EKS cluster load balancer +#------------------------------------------------------------------------------ + +data "aws_eks_cluster" "eks" { + name = var.environment_namespace +} + +data "aws_eks_cluster" "cluster" { + name = var.environment_namespace +} + +data "aws_eks_cluster_auth" "cluster" { + name = var.environment_namespace +} + +provider "kubernetes" { + host = data.aws_eks_cluster.cluster.endpoint + cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data) + token = data.aws_eks_cluster_auth.cluster.token +} + +resource "aws_security_group" "worker_group_mgmt" { + name_prefix = "${var.environment_namespace}-eks_worker_group_mgmt" + description = "openedx_devops: Ingress CLB worker group management" + vpc_id = var.vpc_id + + ingress { + description = "openedx_devops: Ingress CLB" + from_port = 22 + to_port = 22 + protocol = "tcp" + + cidr_blocks = [ + "10.0.0.0/8", + ] + } + + tags = var.tags + +} + +resource "aws_security_group" "all_worker_mgmt" { + name_prefix = "${var.environment_namespace}-eks_all_worker_management" + description = "openedx_devops: Ingress CLB worker management" + vpc_id = var.vpc_id + + ingress { + description = "openedx_devops: Ingress CLB" + from_port = 22 + to_port = 22 + protocol = "tcp" + + cidr_blocks = [ + "10.0.0.0/8", + "172.16.0.0/12", + "192.168.0.0/16", + ] + } + + tags = var.tags + +} + +data "tls_certificate" "cluster" { + url = data.aws_eks_cluster.eks.identity[0].oidc[0].issuer +} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/secrets/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/outputs.tf similarity index 52% rename from {{cookiecutter.github_repo_name}}/terraform/components/secrets/versions.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/outputs.tf index fc0884aa..c4ccde41 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/secrets/versions.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/outputs.tf @@ -3,14 +3,6 @@ # https://www.linkedin.com/in/mmafonso/ # # date: Aug-2021 +# +# usage: build an EKS cluster load balancer #------------------------------------------------------------------------------ -terraform { - required_version = "{{ cookiecutter.terraform_required_version }}" - - required_providers { - aws = { - source = "hashicorp/aws" - version = "{{ cookiecutter.terraform_provider_hashicorp_aws_version }}" - } - } -} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/route53.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/route53.tf similarity index 93% rename from {{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/route53.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/route53.tf index 92298d0f..5a317fdf 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/route53.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/route53.tf @@ -34,7 +34,7 @@ resource "aws_route53_record" "naked" { type = "A" alias { - name = data.kubernetes_service.ingress_nginx_controller.load_balancer_ingress.0.hostname + name = data.kubernetes_service.ingress_nginx_controller.status.0.load_balancer.0.ingress.0.hostname zone_id = data.aws_elb_hosted_zone_id.main.id evaluate_target_health = true } @@ -46,7 +46,7 @@ resource "aws_route53_record" "wildcard" { type = "A" alias { - name = data.kubernetes_service.ingress_nginx_controller.load_balancer_ingress.0.hostname + name = data.kubernetes_service.ingress_nginx_controller.status.0.load_balancer.0.ingress.0.hostname zone_id = data.aws_elb_hosted_zone_id.main.id evaluate_target_health = true } diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/variables.tf new file mode 100644 index 00000000..334f2b20 --- /dev/null +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/variables.tf @@ -0,0 +1,38 @@ +#------------------------------------------------------------------------------ +# written by: Miguel Afonso +# https://www.linkedin.com/in/mmafonso/ +# +# date: Aug-2021 +# +# usage: build an EKS cluster load balancer +#------------------------------------------------------------------------------ +variable "environment_domain" { + type = string +} + +variable "environment_namespace" { + type = string +} + +variable "root_domain" { + description = "Root domain (route53 zone) for the default cluster ingress." + type = string +} + +variable "subdomains" { + description = "Base domain (route53 zone) for the default cluster ingress" + type = list(string) +} + + +variable "tags" { + description = "A map of tags to add to all resources. Tags added to launch configuration or templates override these values for ASG Tags only." + type = map(string) + default = {} +} + + +variable "vpc_id" { + description = "VPC where the cluster and workers will be deployed." + type = string +} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/versions.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/eks_clb_ec2/versions.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_ingress_clb/versions.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/secrets/admin.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/admin.tf similarity index 94% rename from {{cookiecutter.github_repo_name}}/terraform/components/secrets/admin.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/admin.tf index 87f3af69..6557e17b 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/secrets/admin.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/admin.tf @@ -18,7 +18,7 @@ resource "random_password" "admin_edx" { resource "kubernetes_secret" "admin_edx" { metadata { name = "admin-edx" - namespace = var.environment_namespace + namespace = var.namespace } data = { diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/secrets/jwt.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/jwt.tf similarity index 93% rename from {{cookiecutter.github_repo_name}}/terraform/components/secrets/jwt.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/jwt.tf index abcd79c9..89081584 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/secrets/jwt.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/jwt.tf @@ -15,7 +15,7 @@ resource "tls_private_key" "jwt_rsa_private_key" { resource "kubernetes_secret" "jtw" { metadata { name = "jwt" - namespace = var.environment_namespace + namespace = var.namespace } data = { diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/secrets/main.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/kubernetes.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/secrets/main.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/kubernetes.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/secrets/oauth.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/oauth.tf similarity index 95% rename from {{cookiecutter.github_repo_name}}/terraform/components/secrets/oauth.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/oauth.tf index dc67eb4b..fce6a807 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/secrets/oauth.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/oauth.tf @@ -27,7 +27,7 @@ resource "random_password" "clientsecret_edx" { resource "kubernetes_secret" "openedx" { metadata { name = "edx-api" - namespace = var.environment_namespace + namespace = var.namespace } data = { diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/secrets/session.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/session.tf similarity index 94% rename from {{cookiecutter.github_repo_name}}/terraform/components/secrets/session.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/session.tf index a9631ec6..b9224001 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/secrets/session.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/session.tf @@ -18,7 +18,7 @@ resource "random_password" "edx_secret_key" { resource "kubernetes_secret" "edx_secret_key" { metadata { name = "edx-secret-key" - namespace = var.environment_namespace + namespace = var.namespace } data = { diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/jwt/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/variables.tf similarity index 86% rename from {{cookiecutter.github_repo_name}}/terraform/components/jwt/variables.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/variables.tf index 4294326b..75598bf3 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/jwt/variables.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/variables.tf @@ -3,15 +3,16 @@ # https://www.linkedin.com/in/mmafonso/ # # date: Aug-2021 -# -# usage: create a Javascript Web Token (JWT) to be added -# to the Open edX build configuration. #------------------------------------------------------------------------------ variable "environment_namespace" { - description = "kubernetes namespace where to place resources" + description = "universal identifier for most resources" type = string } +variable "namespace" { + description = "kubernetes namespace where to place resources" + type = string +} variable "resource_name" { description = "the full environment-qualified name of this resource." diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/kubernetes/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/versions.tf similarity index 53% rename from {{cookiecutter.github_repo_name}}/terraform/components/kubernetes/versions.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/versions.tf index 25421b09..d71272ac 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/kubernetes/versions.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/kubernetes_secrets/versions.tf @@ -3,16 +3,14 @@ # https://www.linkedin.com/in/mmafonso/ # # date: Aug-2021 -# -# usage: create an EKS cluster. #------------------------------------------------------------------------------ terraform { required_version = "{{ cookiecutter.terraform_required_version }}" required_providers { - aws = { - source = "hashicorp/aws" - version = "{{ cookiecutter.terraform_provider_hashicorp_aws_version }}" - } + aws = "{{ cookiecutter.terraform_provider_hashicorp_aws_version }}" + local = "{{ cookiecutter.terraform_provider_hashicorp_local_version }}" + random = "{{ cookiecutter.terraform_provider_hashicorp_random_version }}" + kubernetes = "{{ cookiecutter.terraform_provider_kubernetes_version }}" } } diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/mongodb/kubernetes.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/mongodb/kubernetes.tf similarity index 96% rename from {{cookiecutter.github_repo_name}}/terraform/components/mongodb/kubernetes.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/mongodb/kubernetes.tf index c1b5f2f0..a9d86d9e 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/mongodb/kubernetes.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/mongodb/kubernetes.tf @@ -39,7 +39,7 @@ resource "random_password" "mongodb_admin" { resource "kubernetes_secret" "mongodb_admin" { metadata { name = "mongodb-admin" - namespace = var.environment_namespace + namespace = "openedx" } data = { diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/mongodb/main.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/mongodb/main.tf similarity index 92% rename from {{cookiecutter.github_repo_name}}/terraform/components/mongodb/main.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/mongodb/main.tf index b896fbeb..4be1321f 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/mongodb/main.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/mongodb/main.tf @@ -7,13 +7,9 @@ # usage: setup a DocumentDB MongoDB cluster with connectivity # to anything inside the VPN. create DNS records for master and reader. #------------------------------------------------------------------------------ -locals { - -} - resource "aws_security_group" "mongo_cluster" { name = var.resource_name - description = "Security Group for DocumentDB cluster" + description = "openedx_devops: DocumentDB cluster" vpc_id = var.vpc_id tags = var.tags } @@ -31,7 +27,7 @@ resource "aws_security_group" "mongo_cluster" { resource "aws_security_group_rule" "ingress_security_groups" { type = "ingress" - description = "Allow inbound traffic from the VPC" + description = "openedx_devops: mongodb llow inbound traffic from the VPC" from_port = var.db_port to_port = var.db_port protocol = "tcp" @@ -74,7 +70,7 @@ resource "aws_docdb_cluster_instance" "default" { resource "aws_docdb_subnet_group" "default" { name = "mongodb_subnet_group" - description = "Allowed subnets for DB cluster instances" + description = "openedx_devops: mongodb allowed subnets for DB cluster instances" subnet_ids = var.subnet_ids tags = var.tags } @@ -87,7 +83,7 @@ resource "aws_docdb_subnet_group" "default" { resource "aws_docdb_cluster_parameter_group" "no_tls" { family = "docdb3.6" name = "mongo-cluster-param-group" - description = "disable tls" + description = "openedx_devops: mongodb - disable tls" parameter { apply_method = "pending-reboot" diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/mongodb/outputs.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/mongodb/outputs.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/mongodb/outputs.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/mongodb/outputs.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/mongodb/route53.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/mongodb/route53.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/mongodb/route53.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/mongodb/route53.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/mongodb/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/mongodb/variables.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/mongodb/variables.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/mongodb/variables.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/mongodb/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/mongodb/versions.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/mongodb/versions.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/mongodb/versions.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/mysql/kubernetes.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/mysql/kubernetes.tf similarity index 94% rename from {{cookiecutter.github_repo_name}}/terraform/components/mysql/kubernetes.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/mysql/kubernetes.tf index bc16b5aa..a80f6ed7 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/mysql/kubernetes.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/mysql/kubernetes.tf @@ -24,7 +24,7 @@ provider "kubernetes" { resource "kubernetes_secret" "mysql_root" { metadata { name = "mysql-root" - namespace = var.environment_namespace + namespace = "openedx" } data = { @@ -48,7 +48,7 @@ resource "random_password" "mysql_openedx" { resource "kubernetes_secret" "openedx" { metadata { name = "mysql-openedx" - namespace = var.environment_namespace + namespace = "openedx" } data = { diff --git a/{{cookiecutter.github_repo_name}}/terraform/modules/mysql/main.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/mysql/main.tf new file mode 100644 index 00000000..7162e3ca --- /dev/null +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/mysql/main.tf @@ -0,0 +1,115 @@ +#------------------------------------------------------------------------------ +# written by: Miguel Afonso +# https://www.linkedin.com/in/mmafonso/ +# +# date: Aug-2021 +# +# usage: create an RDS MySQL instance. +#------------------------------------------------------------------------------ +resource "aws_db_subnet_group" "mysql_subnet_group" { + name = "mysql_subnet_group" + subnet_ids = var.subnet_ids + tags = var.tags +} + +module "security_group" { + source = "terraform-aws-modules/security-group/aws" + version = "{{ cookiecutter.terraform_aws_modules_sg }}" + + name = "${var.environment_namespace}-mysql" + description = "openedx_devops: Allow access to MySQL" + vpc_id = var.vpc_id + + # ingress + ingress_with_cidr_blocks = [ + { + from_port = 3306 + to_port = 3306 + protocol = "tcp" + description = "openedx_devops: MySQL access from within VPC" + cidr_blocks = join(",", var.ingress_cidr_blocks) + }, + ] + + egress_with_cidr_blocks = [ + { + description = "openedx_devops: Node all egress" + protocol = "-1" + from_port = 0 + to_port = 0 + type = "egress" + cidr_blocks = "0.0.0.0/0" + ipv6_cidr_blocks = "::/0" + }, + ] + tags = var.tags +} + + +#------------------------------------------------------------------------------ +# RDS Module +# +# see: https://stackoverflow.com/questions/53386811/terraform-the-db-instance-and-ec2-security-group-are-in-different-vpcs +#------------------------------------------------------------------------------ +module "db" { + source = "terraform-aws-modules/rds/aws" + version = "{{cookiecutter.terraform_aws_modules_rds}}" + + # required parameters (unless we like the default value) + # --------------------------------------------------------------------------- + allocated_storage = var.allocated_storage + #availability_zone = + backup_retention_period = var.backup_retention_period + backup_window = var.backup_window + #ca_cert_identifier = + #character_set_name = + #cloudwatch_log_group_kms_key_id = + db_name = var.name + #db_subnet_group_description = + db_subnet_group_name = aws_db_subnet_group.mysql_subnet_group.name + #domain = + #domain_iam_role_name = + engine = var.engine + engine_version = var.engine_version + family = var.family + identifier = var.identifier + instance_class = var.instance_class + #kms_key_id = + #license_model = + maintenance_window = var.maintenance_window + major_engine_version = var.major_engine_version + #monitoring_role_arn = + #monitoring_role_description = + #option_group_description = + #option_group_name = + #parameter_group_description = + #parameter_group_name = + #password = + #performance_insights_kms_key_id = + port = var.port + #replica_mode = + #replicate_source_db = + #s3_import = + #snapshot_identifier = + #storage_type = + #timezone = + username = var.username + + # optional parameters + # --------------------------------------------------------------------------- + max_allocated_storage = var.max_allocated_storage + storage_encrypted = var.storage_encrypted + create_random_password = var.create_random_password + multi_az = var.multi_az + subnet_ids = var.subnet_ids + vpc_security_group_ids = [module.security_group.security_group_id] + enabled_cloudwatch_logs_exports = var.enabled_cloudwatch_logs_exports + skip_final_snapshot = var.skip_final_snapshot + deletion_protection = var.deletion_protection + performance_insights_enabled = var.performance_insights_enabled + performance_insights_retention_period = var.performance_insights_retention_period + create_monitoring_role = var.create_monitoring_role + monitoring_interval = var.monitoring_interval + parameters = var.parameters + tags = var.tags +} diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/mysql/outputs.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/mysql/outputs.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/mysql/outputs.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/mysql/outputs.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/mysql/route53.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/mysql/route53.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/mysql/route53.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/mysql/route53.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/mysql/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/mysql/variables.tf similarity index 99% rename from {{cookiecutter.github_repo_name}}/terraform/components/mysql/variables.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/mysql/variables.tf index 7c7a19a1..33927de1 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/mysql/variables.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/mysql/variables.tf @@ -177,14 +177,12 @@ variable "storage_encrypted" { variable "subnet_ids" { description = "A list of VPC subnet IDs" type = list(string) - default = [] } variable "vpc_id" { description = "ID of the VPC where to create security groups" type = string - default = null } variable "skip_final_snapshot" { diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/mysql/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/mysql/versions.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/mysql/versions.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/mysql/versions.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/kubernetes.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/kubernetes.tf similarity index 95% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/kubernetes.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/kubernetes.tf index 90fb2424..debf02ea 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/redis/kubernetes.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/kubernetes.tf @@ -24,7 +24,7 @@ provider "kubernetes" { resource "kubernetes_secret" "secret" { metadata { name = "redis" - namespace = var.environment_namespace + namespace = "openedx" } data = { diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/main.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/main.tf similarity index 62% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/main.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/main.tf index 9c80eaed..2d71bd9d 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/redis/main.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/main.tf @@ -18,22 +18,35 @@ locals { module "security_group" { source = "terraform-aws-modules/security-group/aws" - version = "~> 4" + version = "{{ cookiecutter.terraform_aws_modules_sg }}" name = local.name - description = "Allow access to MySQL" + description = "openedx_devops: Allow access to MySQL" vpc_id = var.vpc_id # ingress ingress_with_cidr_blocks = [ { + description = "openedx_devops: Redis access from within VPC" from_port = var.port to_port = var.port protocol = "tcp" - description = "Redis access from within VPC" cidr_blocks = join(",", var.ingress_cidr_blocks) }, ] + + egress_with_cidr_blocks = [ + { + description = "openedx_devops: Node all egress" + protocol = "-1" + from_port = 0 + to_port = 0 + type = "egress" + cidr_blocks = "0.0.0.0/0" + ipv6_cidr_blocks = "::/0" + }, + ] + tags = var.tags } @@ -41,21 +54,15 @@ module "security_group" { module "redis" { source = "./modules/elasticache" - replication_group_description = var.replication_group_description - create_random_auth_token = var.create_random_auth_token - - # DB subnet group - subnet_ids = var.subnet_ids - + description = local.name + create_random_auth_token = var.create_random_auth_token + subnet_ids = var.subnet_ids engine = var.engine engine_version = var.engine_version - number_cache_clusters = var.number_cache_clusters + num_cache_clusters = var.num_cache_clusters port = var.port vpc_security_group_ids = [module.security_group.security_group_id] transit_encryption_enabled = var.transit_encryption_enabled - - - # DB parameter group - family = var.family - node_type = var.node_type + family = var.family + node_type = var.node_type } diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/main.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/main.tf similarity index 64% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/main.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/main.tf index f8f8da79..2cfdcc77 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/main.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/main.tf @@ -3,8 +3,8 @@ locals { elasticache_subnet_group_name = coalesce(var.elasticache_subnet_group_name, module.elasticache_subnet_group.db_subnet_group_id) parameter_group_name_id = var.create_elasticache_parameter_group ? module.elasticache_parameter_group.elasticache_parameter_group_id : var.parameter_group_name - replication_group_id = random_string.id.result - replication_group_description = "elasticache-${random_string.id.result}" + replication_group_id = random_string.id.result + description = "elasticache-${random_string.id.result}" } # Random string to use as auth token @@ -43,17 +43,17 @@ module "elasticache_parameter_group" { #checkov:skip=CKV_AWS_31:Ensure all data stored in the Elasticache Replication Group is securely encrypted at transit and has auth token resource "aws_elasticache_replication_group" "this" { - replication_group_id = local.replication_group_id - replication_group_description = var.replication_group_description - engine = var.engine - engine_version = var.engine_version - node_type = var.node_type - number_cache_clusters = var.number_cache_clusters - port = var.port - subnet_group_name = local.elasticache_subnet_group_name - at_rest_encryption_enabled = var.at_rest_encryption_enabled - transit_encryption_enabled = var.transit_encryption_enabled - auth_token = local.auth_token - parameter_group_name = local.parameter_group_name_id - security_group_ids = var.vpc_security_group_ids + replication_group_id = local.replication_group_id + description = var.description + engine = var.engine + engine_version = var.engine_version + node_type = var.node_type + num_cache_clusters = var.num_cache_clusters + port = var.port + subnet_group_name = local.elasticache_subnet_group_name + at_rest_encryption_enabled = var.at_rest_encryption_enabled + transit_encryption_enabled = var.transit_encryption_enabled + auth_token = local.auth_token + parameter_group_name = local.parameter_group_name_id + security_group_ids = var.vpc_security_group_ids } diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_parameter_group/main.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_parameter_group/main.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_parameter_group/main.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_parameter_group/main.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_parameter_group/outputs.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_parameter_group/outputs.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_parameter_group/outputs.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_parameter_group/outputs.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_parameter_group/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_parameter_group/variables.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_parameter_group/variables.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_parameter_group/variables.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_parameter_group/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_parameter_group/versions.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_parameter_group/versions.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_parameter_group/versions.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_subnet_group/main.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_subnet_group/main.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_subnet_group/main.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_subnet_group/main.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_subnet_group/outputs.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_subnet_group/outputs.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_subnet_group/outputs.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_subnet_group/outputs.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_subnet_group/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_subnet_group/variables.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_subnet_group/variables.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_subnet_group/variables.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_subnet_group/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_subnet_group/versions.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/modules/elasticache_subnet_group/versions.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/modules/elasticache_subnet_group/versions.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/outputs.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/outputs.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/outputs.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/outputs.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/variables.tf similarity index 98% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/variables.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/variables.tf index 5f3dc822..26944eb8 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/variables.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/variables.tf @@ -4,7 +4,7 @@ variable "create_elasticache_instance" { default = true } -variable "replication_group_description" { +variable "description" { description = "A user-created description for the replication group." type = string } @@ -20,7 +20,7 @@ variable "multi_az" { default = false } -variable "number_cache_clusters" { +variable "num_cache_clusters" { description = "The number of cache clusters (primary and replicas) this replication group will have. If Multi-AZ is enabled, the value of this parameter must be at least 2." type = number default = "2" diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/versions.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/modules/elasticache/versions.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/modules/elasticache/versions.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/outputs.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/outputs.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/outputs.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/outputs.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/route53.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/route53.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/route53.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/route53.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/variables.tf similarity index 99% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/variables.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/variables.tf index 38494a15..55ad2374 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/redis/variables.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/variables.tf @@ -32,7 +32,7 @@ variable "multi_az" { default = false } -variable "number_cache_clusters" { +variable "num_cache_clusters" { description = "The number of cache clusters (primary and replicas) this replication group will have. If Multi-AZ is enabled, the value of this parameter must be at least 2." type = number default = "2" diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/redis/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/redis/versions.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/redis/versions.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/redis/versions.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/s3/kubernetes.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/s3_openedx_storage/kubernetes.tf similarity index 65% rename from {{cookiecutter.github_repo_name}}/terraform/components/s3/kubernetes.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/s3_openedx_storage/kubernetes.tf index 15ac4730..da8286c7 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/s3/kubernetes.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/s3_openedx_storage/kubernetes.tf @@ -1,12 +1,3 @@ -#------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ -# -# date: Aug-2021 -# -# usage: create an AWS S3 bucket to offload Open edX file storage. -# store S3 credentials in Kubernetes Secrets. -#------------------------------------------------------------------------------ data "aws_eks_cluster" "eks" { name = var.environment_namespace } @@ -24,7 +15,7 @@ provider "kubernetes" { resource "kubernetes_secret" "s3" { metadata { name = var.secret_name - namespace = var.environment_namespace + namespace = "openedx" } data = { diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/s3/main.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/s3_openedx_storage/main.tf similarity index 96% rename from {{cookiecutter.github_repo_name}}/terraform/components/s3/main.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/s3_openedx_storage/main.tf index 0dc06e9c..72250faa 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/s3/main.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/s3_openedx_storage/main.tf @@ -6,9 +6,10 @@ # # usage: create an AWS S3 bucket to offload Open edX file storage. #------------------------------------------------------------------------------ + module "data_backup_s3_bucket" { source = "terraform-aws-modules/s3-bucket/aws" - version = "~> 2" + version = "{{ cookiecutter.terraform_aws_modules_s3 }}" bucket = var.resource_name acl = "private" diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/s3/outputs.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/s3_openedx_storage/outputs.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/s3/outputs.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/s3_openedx_storage/outputs.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/s3/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/s3_openedx_storage/variables.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/s3/variables.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/s3_openedx_storage/variables.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/s3/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/s3_openedx_storage/versions.tf similarity index 80% rename from {{cookiecutter.github_repo_name}}/terraform/components/s3/versions.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/s3_openedx_storage/versions.tf index dd3e4cca..76a20c54 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/s3/versions.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/s3_openedx_storage/versions.tf @@ -11,8 +11,7 @@ terraform { required_providers { aws = { - source = "hashicorp/aws" - version = "{{ cookiecutter.terraform_provider_hashicorp_aws_version }}" + source = "hashicorp/aws" } } } diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/vpc/README.md b/{{cookiecutter.github_repo_name}}/terraform/modules/vpc/README.md similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/vpc/README.md rename to {{cookiecutter.github_repo_name}}/terraform/modules/vpc/README.md diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/vpc/main.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/vpc/main.tf similarity index 53% rename from {{cookiecutter.github_repo_name}}/terraform/components/vpc/main.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/vpc/main.tf index 17baf959..3c096425 100644 --- a/{{cookiecutter.github_repo_name}}/terraform/components/vpc/main.tf +++ b/{{cookiecutter.github_repo_name}}/terraform/modules/vpc/main.tf @@ -1,8 +1,8 @@ #------------------------------------------------------------------------------ -# written by: Miguel Afonso -# https://www.linkedin.com/in/mmafonso/ +# written by: Lawrence McDaniel +# https://lawrencemcdaniel.com # -# date: Aug-2021 +# date: mar-2022 # # usage: create a VPC to contain all Open edX backend resources. # this VPC is configured to generally use all AWS defaults. @@ -13,9 +13,10 @@ # see https://registry.terraform.io/modules/terraform-aws-modules/vpc/aws/latest #------------------------------------------------------------------------------ + module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3" + version = "{{ cookiecutter.terraform_aws_modules_vpc }}" create_vpc = true name = var.name cidr = var.cidr @@ -31,25 +32,5 @@ module "vpc" { one_nat_gateway_per_az = var.one_nat_gateway_per_az public_subnet_tags = var.public_subnet_tags private_subnet_tags = var.private_subnet_tags - - #---------------------------------------------------------------------------- - # Sometimes it is handy to have public access to RDS instances - # (it is not recommended for production) by specifying these arguments: - #---------------------------------------------------------------------------- - #create_database_subnet_group = true - #create_database_subnet_route_table = true - #create_database_internet_gateway_route = true - #enable_dns_hostnames = true - #enable_dns_support = true - - #---------------------------------------------------------------------------- - # Optional Settings for Network Access Control Lists (ACL or NACL) - # example: https://github.com/terraform-aws-modules/terraform-aws-vpc/blob/master/examples/network-acls/main.tf - #---------------------------------------------------------------------------- - #manage_default_network_acl = true - #public_dedicated_network_acl = true - #public_inbound_acl_rules = - #public_outbound_acl_rules = - - tags = var.tags + tags = var.tags } diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/vpc/outputs.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/vpc/outputs.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/vpc/outputs.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/vpc/outputs.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/vpc/variables.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/vpc/variables.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/vpc/variables.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/vpc/variables.tf diff --git a/{{cookiecutter.github_repo_name}}/terraform/components/vpc/versions.tf b/{{cookiecutter.github_repo_name}}/terraform/modules/vpc/versions.tf similarity index 100% rename from {{cookiecutter.github_repo_name}}/terraform/components/vpc/versions.tf rename to {{cookiecutter.github_repo_name}}/terraform/modules/vpc/versions.tf