Rationale: Currently we have multiple deployments that span across multiple cloud accounts. Each deployment has a separate terraform codebase, with some TF modules shared. As our deployments grow, managing each terraform configuration separately becomes less and less viable. We need to move to a more scalable solution and the goal of this assignment is to create a simple demo of some approach for the solution.
Please publish your solution in a publicly available git repository. All code, scripts and possibly documentation should be committed into this repository. If manual steps are performed (eg. start a docker-compose or terraform commands), they should be documented so everybody familiar with the technologies is able to reproduce the steps. Each task should be represented as one or more commits in the repository.
- Everything must run locally using Docker/Docker Compose
- No cloud services should be used
- Solution must be in a public git repository
- All manual steps must be documented
- Each task should be separate commits
- GitHub action for Terraform validation
- [IN PROGRESS] Use Terragrunt for 2nd task
- branch: terragrung
- Currently problems with downloading providers from Hashicorp
Details
``` 23:24:10.579 STDOUT terraform: Initializing the backend... 23:24:10.615 STDOUT terraform: Initializing provider plugins... 23:24:10.615 STDOUT terraform: - Finding cyrilgdn/postgresql versions matching "~> 1.21.0"... 23:24:10.803 STDOUT terraform: - Finding hashicorp/random versions matching "3.6.3"... 23:24:35.602 STDOUT terraform: - Installing hashicorp/random v3.6.3... 23:24:36.087 STDOUT terraform: - Installed hashicorp/random v3.6.3 (signed by HashiCorp) 23:24:36.087 STDOUT terraform: ╷ 23:24:36.087 STDOUT terraform: │ Error: Failed to install provider 23:24:36.087 STDOUT terraform: │ 23:24:36.087 STDOUT terraform: │ Error while installing cyrilgdn/postgresql v1.21.0: could not query 23:24:36.087 STDOUT terraform: │ provider registry for registry.terraform.io/cyrilgdn/postgresql: failed to 23:24:36.087 STDOUT terraform: │ retrieve cryptographic signature for provider: the request failed after 2 23:24:36.087 STDOUT terraform: │ attempts, please try again later: Get 23:24:36.087 STDOUT terraform: │ "https://github.com/cyrilgdn/terraform-provider-postgresql/releases/download/v1.21.0/terraform-provider-postgresql_1.21.0_SHA256SUMS.sig": 23:24:36.087 STDOUT terraform: │ context deadline exceeded 23:24:36.087 STDOUT terraform: ╵ 23:24:36.090 ERROR terraform invocation failed in /home/waldauf/__JOB/__ROSSUM/rossum-homework/grunt-02/clusters/dev/.terragrunt-cache/rzHbUrxhpsx1alZf4xU4KDor6YU/mhGmks4mczjF3JZlKaF8nz364B4 error=[/home/waldauf/__JOB/__ROSSUM/rossum-homework/grunt-02/clusters/dev/.terragrunt-cache/rzHbUrxhpsx1alZf4xU4KDor6YU/mhGmks4mczjF3JZlKaF8nz36 4B4] exit status 1 23:24:36.090 ERROR 1 error occurred: * [/home/waldauf/__JOB/__ROSSUM/rossum-homework/grunt-02/clusters/dev/.terragrunt-cache/rzHbUrxhpsx1alZf4xU4KDor6YU/mhGmks4mczjF3JZlKaF8nz364B4] exit status 1 ```
- Currently problems with downloading providers from Hashicorp
- Create a docker-compose.yml file that:
- Runs a PostgreSQL database
- Makes it accessible only from localhost
- Sets up root password (can be visible in git)
- Create a Terraform module that:
- Creates 3 databases
- Creates 3 pairs of users (each with full access to one database)
- Creates 1 read-only user with access to all databases
- Manages secure passwords (must not be visible in git)
- Can use local terraform state
- Extend docker-compose.yml to:
- Run multiple PostgreSQL instances (suggested 3)
- Each instance on different ports
- Each instance simulates a separate deployment/AWS account
- Apply the same Terraform configuration to each instance:
- Same database and user structure
- Unique passwords for each instance
- Should be easily scalable to add more instances
terraform(version ~> 1.7)dockerdocker-compose
- Switch to the task 1 directory:
cd ./terraform-01- Run PostgreSQL instance as docker container:
cd docker
docker-compose up -d
docker-compose ps -a
cd ..- Run
terraformfor applying PostgreSQL configuration:
# Initialize Terraform (load all necessary providers)
terraform init
# Check the output if everything is alright
terraform plan -out postgres_configuration.tfplan
# Apply changes
terraform apply postgres_configuration.tfplan- View all users and their passwords from the
terraform.tfstatefile:
jq -r '.outputs.all_users_passwords.value | to_entries[] | "\(.key) => \(.value)"' terraform.tfstate- Verify PostgreSQL configuration:
# List all databases
PGPASSWORD="root" psql -h localhost -p 5432 -U root -d postgres -c "\l"
# List all users
PGPASSWORD="root" psql -h localhost -p 5432 -U root -d postgres -c "\du"- Clean up (when done):
terraform apply -destroy
cd docker
docker-compose down
sudo rm -rf postgres_data
cd ..- Switch to the task 2 directory:
cd ./terraform-02- Run all PostgreSQL instances as docker containers:
cd docker
docker-compose up -d
docker-compose ps -a
cd ..Each instance is running on different ports:
- DEV: 5432
- TEST: 5433
- PROD: 5434
- Configure each environment (example for DEV):
# Switch to DEV configuration
cd clusters/dev
# Initialize Terraform
terraform init
# Plan changes
terraform plan -out postgres_configuration.tfplan
# Apply changes
terraform apply postgres_configuration.tfplanRepeat for TEST and PROD environments by changing to the appropriate directory.
- View passwords for a specific environment:
jq -r '.outputs.all_users_passwords.value | to_entries[] | "\(.key) => \(.value)"' terraform.tfstate- Verify PostgreSQL configuration (adjust port based on environment):
# For DEV environment (port 5432)
PGPASSWORD="root" psql -h localhost -p 5432 -U root -d postgres -c "\du"
PGPASSWORD="root" psql -h localhost -p 5432 -U root -d postgres -c "\l"
# For TEST environment (port 5433)
PGPASSWORD="root" psql -h localhost -p 5433 -U root -d postgres -c "\du"
PGPASSWORD="root" psql -h localhost -p 5433 -U root -d postgres -c "\l"
# For PROD environment (port 5434)
PGPASSWORD="root" psql -h localhost -p 5434 -U root -d postgres -c "\du"
PGPASSWORD="root" psql -h localhost -p 5434 -U root -d postgres -c "\l"- Clean up all environments:
# For each environment
cd clusters/dev
terraform apply -destroy
cd ../test
terraform apply -destroy
cd ../prod
terraform apply -destroy
# Remove containers and volumes
cd ../../docker
docker-compose down
sudo rm -rf postgres_data*- Use mainly official or supported providers by Hashicorp
- All passwords should be loaded during CD pipeline to:
- Prevent possible leakage
- Avoid manual manipulation
- In this implementation, we prevent sharing by adding
terraform.tfstateto.gitignorefile
- State should be stored in a remote backend to support team collaboration
- Remote state enables locking to prevent concurrent modifications
CI
- Run formatting, validation, and security scans on each pull request
- Implement linting and policy checks to ensure best practices
CD
- Manage sensitive data like passwords as part of the CD pipeline
- Consider whether the
applyprocess should be automated or require manual approval