Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mv aws module to addons, adding example usage, adding readme with tfdocs #9

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 92 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,92 @@
# terraform-kubernetes-django
Deploy Django with Terraform to Kubernetes with optional support for AWS/EKS or GCP/GKE
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.0 |
| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >= 2.4.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_kubernetes"></a> [kubernetes](#provider\_kubernetes) | >= 2.4.0 |

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_addons_aws_bucket"></a> [addons\_aws\_bucket](#module\_addons\_aws\_bucket) | ./modules/terraform-aws-addon-file-storage | n/a |
| <a name="module_cloudflare"></a> [cloudflare](#module\_cloudflare) | ./modules/cloudflare | n/a |
| <a name="module_deployment"></a> [deployment](#module\_deployment) | djangoflow/deployment/kubernetes | >=2.5.1 |
| <a name="module_gcp"></a> [gcp](#module\_gcp) | ./modules/gcp | n/a |
| <a name="module_postgresql"></a> [postgresql](#module\_postgresql) | djangoflow/postgresql/kubernetes | 1.1.2 |
| <a name="module_redis"></a> [redis](#module\_redis) | djangoflow/redis/kubernetes | n/a |

## Resources

| Name | Type |
|------|------|
| [kubernetes_horizontal_pod_autoscaler_v1.hpa](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/horizontal_pod_autoscaler_v1) | resource |
| [kubernetes_ingress_v1.ingress](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/ingress_v1) | resource |
| [kubernetes_namespace_v1.namespace](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace_v1) | resource |
| [kubernetes_persistent_volume_claim_v1.pgdata](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume_claim_v1) | resource |
| [kubernetes_pod_disruption_budget_v1.pdb](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/pod_disruption_budget_v1) | resource |
| [kubernetes_secret_v1.secrets](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret_v1) | resource |
| [kubernetes_service_account_v1.service_account](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service_account_v1) | resource |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_addons"></a> [addons](#input\_addons) | list of addons to enable | <pre>map(object({<br> addon_type = string<br> config = any<br> }))</pre> | `{}` | no |
| <a name="input_celery_beat_defaults"></a> [celery\_beat\_defaults](#input\_celery\_beat\_defaults) | n/a | `map` | <pre>{<br> "args": [<br> "/start-celerybeat"<br> ],<br> "command": null,<br> "env": {},<br> "hpa_max_replicas": 0,<br> "liveness_probe": {<br> "command": [],<br> "enabled": false<br> },<br> "name": "celery-beat",<br> "pdb_min_available": 0,<br> "port": 0,<br> "pre_install_command": [],<br> "pre_install_migrate": false,<br> "readiness_probe": {<br> "command": [],<br> "enabled": false<br> },<br> "replicas": 1,<br> "resources_limits_cpu": "250m",<br> "resources_limits_memory": "256Mi",<br> "resources_requests_cpu": "30m",<br> "resources_requests_memory": "90Mi"<br>}</pre> | no |
| <a name="input_celery_db_index"></a> [celery\_db\_index](#input\_celery\_db\_index) | n/a | `string` | `"2"` | no |
| <a name="input_celery_enabled"></a> [celery\_enabled](#input\_celery\_enabled) | A short-hand for adding celery-beat and celery-worker deployments | `bool` | `true` | no |
| <a name="input_celery_worker_defaults"></a> [celery\_worker\_defaults](#input\_celery\_worker\_defaults) | n/a | `map` | <pre>{<br> "args": [<br> "/start-celeryworker"<br> ],<br> "command": null,<br> "env": {},<br> "hpa_max_replicas": 0,<br> "liveness_probe": {<br> "command": [<br> "celery",<br> "-A",<br> "config.celery_app",<br> "inspect",<br> "ping"<br> ],<br> "enabled": true<br> },<br> "name": "celery-worker",<br> "pdb_min_available": 0,<br> "port": 0,<br> "pre_install_command": [],<br> "pre_install_migrate": false,<br> "readiness_probe": {<br> "command": [],<br> "enabled": false<br> },<br> "replicas": 1,<br> "resources_limits_cpu": "900m",<br> "resources_limits_memory": "768Mi",<br> "resources_requests_cpu": "100m",<br> "resources_requests_memory": "128Mi"<br>}</pre> | no |
| <a name="input_cloud_sa_name"></a> [cloud\_sa\_name](#input\_cloud\_sa\_name) | Name of the GCP/AWS service account if any | `string` | `null` | no |
| <a name="input_cloudflare_enabled"></a> [cloudflare\_enabled](#input\_cloudflare\_enabled) | Create cloudflare records if true | `bool` | `true` | no |
| <a name="input_create_namespace"></a> [create\_namespace](#input\_create\_namespace) | Should we create the namespace or use existing provided? | `bool` | `true` | no |
| <a name="input_deployments"></a> [deployments](#input\_deployments) | Deployments | <pre>map(object({<br> name = string<br> replicas = optional(number, 1)<br> command = optional(list(string))<br> args = optional(list(string), ["/start"])<br> port = optional(number)<br> resources_requests_cpu = optional(string, "100m")<br> resources_requests_memory = optional(string, "256Mi")<br> resources_limits_cpu = optional(string, "1000m")<br> resources_limits_memory = optional(string, "2Gi")<br> pdb_min_available = optional(number, 0)<br> hpa_min_replicas = optional(number, 0)<br> hpa_max_replicas = optional(number, 0)<br> hpa_target_cpu = optional(number, 80)<br> pre_install_migrate = optional(bool, false)<br> pre_install_command = optional(list(string), [])<br> env = optional(map(string))<br> liveness_probe = optional(object({<br> enabled = optional(bool, true)<br> http_get = optional(object({<br> path = string<br> port = number<br> scheme = string<br> }))<br> command = optional(list(string), [])<br> success_threshold = optional(number)<br> failure_threshold = optional(number)<br> initial_delay_seconds = optional(number)<br> period_seconds = optional(number)<br> timeout_seconds = optional(number)<br> }))<br> readiness_probe = optional(object({<br> enabled = optional(bool, true)<br> http_get = optional(object({<br> path = string<br> port = number<br> scheme = string<br> }))<br> command = optional(list(string), [])<br> success_threshold = optional(number)<br> failure_threshold = optional(number)<br> initial_delay_seconds = optional(number)<br> period_seconds = optional(number)<br> timeout_seconds = optional(number)<br> }))<br> }))</pre> | <pre>{<br> "web": {<br> "name": "web",<br> "port": 5000,<br> "pre_install_command": [],<br> "pre_install_migrate": true,<br> "replicas": 1<br> }<br>}</pre> | no |
| <a name="input_env"></a> [env](#input\_env) | A map of extra environment variables | `map(string)` | `{}` | no |
| <a name="input_extra_labels"></a> [extra\_labels](#input\_extra\_labels) | Extra labels to add to generated objects | `map(string)` | `{}` | no |
| <a name="input_gcp_add_aws_s3_env"></a> [gcp\_add\_aws\_s3\_env](#input\_gcp\_add\_aws\_s3\_env) | Add AWS\_ variables for the GCS bucket | `bool` | `false` | no |
| <a name="input_gcp_bucket_location"></a> [gcp\_bucket\_location](#input\_gcp\_bucket\_location) | The location of the bucket, e.g. EU or US | `string` | n/a | yes |
| <a name="input_gcp_bucket_name"></a> [gcp\_bucket\_name](#input\_gcp\_bucket\_name) | Create and use Google storage with this name | `string` | `null` | no |
| <a name="input_gcp_db_instance"></a> [gcp\_db\_instance](#input\_gcp\_db\_instance) | Create a database and a user for this installation and use them instead of DATABASE\_URL | `string` | `null` | no |
| <a name="input_gcp_sa_extra_roles"></a> [gcp\_sa\_extra\_roles](#input\_gcp\_sa\_extra\_roles) | Create role bindings to these roles | `list(string)` | `null` | no |
| <a name="input_image_name"></a> [image\_name](#input\_image\_name) | Docker image repository and name | `string` | n/a | yes |
| <a name="input_image_pull_policy"></a> [image\_pull\_policy](#input\_image\_pull\_policy) | Pull policy for the images | `string` | `"IfNotPresent"` | no |
| <a name="input_image_pull_secrets"></a> [image\_pull\_secrets](#input\_image\_pull\_secrets) | Image pull secrets | `list(string)` | `[]` | no |
| <a name="input_image_tag"></a> [image\_tag](#input\_image\_tag) | Docker image tag | `string` | n/a | yes |
| <a name="input_ingress"></a> [ingress](#input\_ingress) | A map of hostnames with maps of path-names and services | `map(map(string))` | n/a | yes |
| <a name="input_ingress_annotations"></a> [ingress\_annotations](#input\_ingress\_annotations) | n/a | `map(string)` | `{}` | no |
| <a name="input_liveness_probe"></a> [liveness\_probe](#input\_liveness\_probe) | Liveness probe for containers which have ports | <pre>object({<br> http_get = object({<br> path = string<br> port = number<br> scheme = string<br> })<br> success_threshold = number<br> failure_threshold = number<br> initial_delay_seconds = number<br> period_seconds = number<br> timeout_seconds = number<br> })</pre> | <pre>{<br> "failure_threshold": 3,<br> "http_get": {<br> "path": "/healthz/",<br> "port": 5000,<br> "scheme": "HTTP"<br> },<br> "initial_delay_seconds": 20,<br> "period_seconds": 30,<br> "success_threshold": 1,<br> "timeout_seconds": 5<br>}</pre> | no |
| <a name="input_name"></a> [name](#input\_name) | The name for deployment | `string` | `"django"` | no |
| <a name="input_namespace"></a> [namespace](#input\_namespace) | Kubernetes namespace to use with this installation | `string` | n/a | yes |
| <a name="input_postgres_enabled"></a> [postgres\_enabled](#input\_postgres\_enabled) | Create a postgres database deployment | `bool` | `false` | no |
| <a name="input_postgres_resources_limits_cpu"></a> [postgres\_resources\_limits\_cpu](#input\_postgres\_resources\_limits\_cpu) | n/a | `string` | `null` | no |
| <a name="input_postgres_resources_limits_memory"></a> [postgres\_resources\_limits\_memory](#input\_postgres\_resources\_limits\_memory) | n/a | `string` | `null` | no |
| <a name="input_postgres_resources_requests_cpu"></a> [postgres\_resources\_requests\_cpu](#input\_postgres\_resources\_requests\_cpu) | n/a | `string` | `"250m"` | no |
| <a name="input_postgres_resources_requests_memory"></a> [postgres\_resources\_requests\_memory](#input\_postgres\_resources\_requests\_memory) | n/a | `string` | `"256Mi"` | no |
| <a name="input_postgres_storage_size"></a> [postgres\_storage\_size](#input\_postgres\_storage\_size) | n/a | `string` | `"10Gi"` | no |
| <a name="input_public_storage"></a> [public\_storage](#input\_public\_storage) | Make the storge GCP bucket/AWS S3 public and create a CNAME | `bool` | `true` | no |
| <a name="input_readiness_probe"></a> [readiness\_probe](#input\_readiness\_probe) | Readiness probe for containers which have ports | <pre>object({<br> http_get = object({<br> path = string<br> port = number<br> scheme = string<br> })<br> success_threshold = number<br> failure_threshold = number<br> initial_delay_seconds = number<br> period_seconds = number<br> timeout_seconds = number<br> })</pre> | <pre>{<br> "failure_threshold": 3,<br> "http_get": {<br> "path": "/healthz/",<br> "port": 5000,<br> "scheme": "HTTP"<br> },<br> "initial_delay_seconds": 20,<br> "period_seconds": 30,<br> "success_threshold": 1,<br> "timeout_seconds": 5<br>}</pre> | no |
| <a name="input_redis_db_index"></a> [redis\_db\_index](#input\_redis\_db\_index) | n/a | `string` | `"1"` | no |
| <a name="input_redis_enabled"></a> [redis\_enabled](#input\_redis\_enabled) | Create a redis database deployment | `bool` | `false` | no |
| <a name="input_redis_resources_limits_cpu"></a> [redis\_resources\_limits\_cpu](#input\_redis\_resources\_limits\_cpu) | n/a | `string` | `null` | no |
| <a name="input_redis_resources_limits_memory"></a> [redis\_resources\_limits\_memory](#input\_redis\_resources\_limits\_memory) | n/a | `string` | `null` | no |
| <a name="input_redis_resources_requests_cpu"></a> [redis\_resources\_requests\_cpu](#input\_redis\_resources\_requests\_cpu) | n/a | `string` | `"50m"` | no |
| <a name="input_redis_resources_requests_memory"></a> [redis\_resources\_requests\_memory](#input\_redis\_resources\_requests\_memory) | n/a | `string` | `"128Mi"` | no |
| <a name="input_secret_env"></a> [secret\_env](#input\_secret\_env) | A map of extra secret environment variables | `map(string)` | n/a | yes |
| <a name="input_security_context_enabled"></a> [security\_context\_enabled](#input\_security\_context\_enabled) | n/a | `bool` | `false` | no |
| <a name="input_security_context_fsgroup"></a> [security\_context\_fsgroup](#input\_security\_context\_fsgroup) | n/a | `any` | `null` | no |
| <a name="input_security_context_gid"></a> [security\_context\_gid](#input\_security\_context\_gid) | n/a | `number` | `101` | no |
| <a name="input_security_context_uid"></a> [security\_context\_uid](#input\_security\_context\_uid) | n/a | `number` | `101` | no |
| <a name="input_service_account_name"></a> [service\_account\_name](#input\_service\_account\_name) | Name of the kubernetes service account if any | `string` | `null` | no |
| <a name="input_volumes"></a> [volumes](#input\_volumes) | Volume configuration | `any` | `[]` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_database_url"></a> [database\_url](#output\_database\_url) | n/a |
10 changes: 10 additions & 0 deletions addons_aws_s3.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
locals {
aws_buckets = {for k,v in var.addons : k => v if v.addon_type == "aws.bucket"}
}

module "addons_aws_bucket" {
for_each = local.aws_buckets
source = "./modules/terraform-aws-addon-file-storage"
name = each.value.config.name
username = each.value.config.username
}
7 changes: 0 additions & 7 deletions aws.tf

This file was deleted.

30 changes: 30 additions & 0 deletions examples/simpleapp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0.0 |

## Providers

No providers.

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_django_app"></a> [django\_app](#module\_django\_app) | ../../ | n/a |

## Resources

No resources.

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_aws"></a> [aws](#input\_aws) | n/a | <pre>object({<br> region = string<br> profile = string<br> })</pre> | n/a | yes |
| <a name="input_cloudflare"></a> [cloudflare](#input\_cloudflare) | n/a | <pre>object({<br> api_key = string<br> email = string<br> })</pre> | <pre>{<br> "api_key": "",<br> "email": ""<br>}</pre> | no |

## Outputs

No outputs.
9 changes: 9 additions & 0 deletions examples/simpleapp/config.auto.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cloudflare = {
api_key = "a9fcaab0378b7d2c4c74ab0663b25e53c5b4f"
email = "[email protected]"
}

aws = {
region = "us-east-1"
profile = "me"
}
68 changes: 68 additions & 0 deletions examples/simpleapp/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
locals {
app_name = "djangoflow-apexive-magusd"
}
module "django_app" {
source = "../../"

service_account_name = local.app_name

gcp_bucket_location = "US"
image_name = "nginx"
image_tag = "latest"
ingress = {
"api.demo.djangoflow.com" : {
"/" : "api"
}
}
namespace = "djangoflow-test-simpleapp"
secret_env = {
"DATABASE_URL" = "127.0.0.1"
"REDIS_URL" = "127.0.0.1"
}

deployments = {
simpleapp = {
name = "simpleapp"
port = 80
liveness_probe = {
enabled = true
http_get = {
path = "/"
port = 80
scheme = "HTTP"
}
success_threshold = 1
failure_threshold = 3
initial_delay_seconds = 5
period_seconds = 10
timeout_seconds = 1
}

readiness_probe = {
enabled = true
http_get = {
path = "/"
port = 80
scheme = "HTTP"
}
success_threshold = 1
failure_threshold = 3
initial_delay_seconds = 5
period_seconds = 10
timeout_seconds = 1
}
}
}


addons = {
media = {
addon_type = "aws.bucket"
config = {
name = local.app_name
username = local.app_name
public = true
}
}
}
}
17 changes: 17 additions & 0 deletions examples/simpleapp/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

provider "cloudflare" {
api_key = var.cloudflare.api_key
email = var.cloudflare.email
}

provider "aws" {
region = var.aws.region
profile = var.aws.profile
}

provider "google" {
# project = "apexive-magusd"
# region = "us-east1"
project = "none"
region = "none"
}
17 changes: 17 additions & 0 deletions examples/simpleapp/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
variable "cloudflare" {
type = object({
api_key = string
email = string
})
default = {
api_key = ""
email = ""
}
}

variable "aws" {
type = object({
region = string
profile = string
})
}
12 changes: 12 additions & 0 deletions examples/simpleapp/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0.0"
}

cloudflare = {
source = "cloudflare/cloudflare"
}
}
}
10 changes: 5 additions & 5 deletions locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ locals {
AWS_STORAGE_BUCKET_NAME : var.gcp_bucket_name
AWS_S3_ENDPOINT_URL : "https://storage.googleapis.com"
}
aws_env = var.aws_s3_name == null ? {} : {
AWS_ACCESS_KEY_ID : module.aws.0.aws_iam_access_key.id
AWS_SECRET_ACCESS_KEY : module.aws.0.aws_iam_access_key.secret
AWS_STORAGE_BUCKET_NAME : var.aws_s3_name
AWS_S3_ENDPOINT_URL : module.aws.0.aws_s3_endpoint_url
aws_env = length(local.aws_buckets) > 0 ? {} : {
AWS_ACCESS_KEY_ID : module.addons_aws_bucket.0.aws_iam_access_key.id
AWS_SECRET_ACCESS_KEY : module.addons_aws_bucket.0.aws_iam_access_key.secret
AWS_STORAGE_BUCKET_NAME : local.aws_buckets.0.config.name
AWS_S3_ENDPOINT_URL : module.addons_aws_bucket.0.aws_s3_endpoint_url
}

env = merge(local.gcp_env, local.aws_env, var.env)
Expand Down
21 changes: 0 additions & 21 deletions modules/aws/iam.tf

This file was deleted.

7 changes: 0 additions & 7 deletions modules/aws/main.tf

This file was deleted.

7 changes: 0 additions & 7 deletions modules/aws/outputs.tf

This file was deleted.

24 changes: 0 additions & 24 deletions modules/aws/storage.tf

This file was deleted.

Loading