Terraform — это инструмент, который позволяет управлять инфраструктурой как кодом (IaC). С помощью Terraform вы можете определить вашу инфраструктуру в простых конфигурационных файлах, и сервис автоматически создаст вашу инфраструктуру в соответствии с этими конфигурациями.
Terragrunt — это легкая обертка для Terraform, которая предоставляет дополнительные инструменты для поддержания ваших конфигураций в DRY (Don't Repeat Yourself) стиле, управления удаленным состоянием и работы с несколькими модулями Terraform. Terragrunt помогает поддерживать чистоту и повторяемость кода Terraform, обеспечивая дополнительный функционал и лучшие практики.
В паре эти инструменты дают такие преимущества:
Инструкции по установке можно найти в официальной документации:
Ниже приведена структура, наиболее подходящая для организации компонентов, концепций и настройки Keycloak.
.
├── README.md <- The project overview
├── .tool-versions <- Used tools versions (managed by asdf. see https://asdf-vm.com)
├── README.md <- The project overview
├── modules <- Terraform modules
| └── common
│ ├── provider.tf
│ └── variables.tf
│ └── output.tf
│ └── main.tf
│ └── README.md
│ └── docs/
| └── clients
│ ├── provider.tf
│ └── variables.tf
│ └── output.tf
│ └── main.tf
│ └── README.md
│ └── docs/
| └── my-realm
│ ├── provider.tf
│ └── variables.tf
│ └── output.tf
│ └── main.tf
│ └── README.md
│ └── docs/
| └── other
│ ├── provider.tf
│ └── variables.tf
│ └── output.tf
│ └── main.tf
│ └── README.md
│ └── docs/
└── how-to <- Documentation
└── stage <- Terraform for environment stage
├── .terraform.lock.hcl <- Terraform lock file
└── terragrunt.hcl <- Terragrunt file
└── env.yaml <- environment related variables
└── main.tf <- environment modules
└── prod <- Terraform for environment prod
├── .terraform.lock.hcl <- Terraform lock file
└── terragrunt.hcl <- Terragrunt file
└── env.yaml <- environment related variables
└── main.tf <- environment modules
└── local <- Terraform for environment local
├── .terraform.lock.hcl <- Terraform lock file
└── terragrunt.hcl <- Terragrunt file
└── env.yaml <- environment related variables
└── main.tf <- environment modules
Каждый модуль включает файл main.tf, инкапсулирующий ресурсы модуля, а также файлы input.tf, output.tf, и variable.tfдля легкой настройки в разных средах.
Common-модуль
Предположим, что в common модуле мы настраиваем события реального времени, используя слушатель событий jboss-logging с некоторыми нестандартными конфигурациями. Ниже приведен пример того, как может выглядеть файл main.tf:
resource "keycloak_realm_events" "realm_events" {
realm_id = var.realm_id
events_enabled = true
events_expiration = 1800
admin_events_enabled = true
admin_events_details_enabled = true
]
events_listeners = [
"jboss-logging"
]
}
Чтобы включить переменную realm_id, ее необходимо определить в variables.tf, как показано ниже:
variable "realm_id" {
description = "Realm ID"
type = string
}
Также стоит настроить используемые провайдеры в нашем модуле. В этом случае provider.tf будет выглядеть так:
terraform {
required_providers {
keycloak = {
source = "mrparkers/keycloak"
}
}
}
Модуль Master Realm
В realm-master модуле main.tf должен ссылаться на common. Вот пример того, как main.tf может выглядеть:
data "keycloak_realm" "master" {
realm = "master"
}
module "realm-master" {
source = "../../modules/common"
realm_id = data.keycloak_realm.master.id
}
Файл provider.tf настраиваем аналогично:
terraform {
required_providers {
keycloak = {
source = "mrparkers/keycloak"
}
}
}
Local environment
В main.tf нам необходимо определить главную область, чтобы ссылаться на realm-master модуль в нашем проекте.
# Define master realm
module "realm-master" {
source = "../modules/realm-master"
}
В каждой среде (например, prod, stage и local) есть env.yaml, содержащий все переменные, специфичные для этой среды.
Например, env.yaml для локальной среды может выглядеть так:
---
environment: local
url: http://localhost:8080/keycloak
И, конечно же, не забудьте включить файл terragrunt-local.hcl, который должен быть определен в родительском модуле.
include "root" {
path = find_in_parent_folders("terragrunt-local.hcl")
}
Terragrunt очень полезен для сохранения конфигурации Don't Repeat Yourself (DRY). Например, файл terragrunt.hcl может выглядеть так:
# Generates the backend for all modules.
remote_state {
backend = "s3"
config = {
encrypt = true
key = "keycloak/${path_relative_to_include()}/terraform.tfstate"
region = "<AWS REGION>"
bucket = "terraform-states"
dynamodb_table = "terraform-lock"
}
}
# Read the local "env.yaml" in every environment.
locals {
vars = yamldecode(file("${path_relative_to_include()}/env.yaml"))
environment = local.vars.environment
url = local.vars.url
}
# Generate the "provider.tf" file for every module.
generate "provider" {
path = "provider.tf"
if_exists = "overwrite"
contents = <<EOF
terraform {
required_providers {
keycloak = {
source = "mrparkers/keycloak"
version = "4.4.0"
}
http = {
source = "hashicorp/http"
version = "3.2.1"
}
}
}
data "http" "config" {
url = "<INTERNAL CONFIGURATION URL>"
}
provider "keycloak" {
client_id = jsondecode(data.http.config.response_body).terraform-client-id
client_secret = jsondecode(data.http.config.response_body).terraform-client-secret
url = "${local.url}"
}
EOF
}
# Generate the "backend.tf" file for every module.
generate "backend" {
path = "backend.tf"
if_exists = "overwrite"
contents = <<EOF
terraform {
backend "s3" {}
}
EOF
}
В remote_state мы используем AWS S3 для хранения состояния наших конфигураций среды. Кроме того, мы генерируем backend и providerдля каждой среды.
Блок locals в основном используется для чтения env.yaml и назначения переменных.
Наконец, http config отвечает за выполнение HTTP-вызова туда, где вы безопасно храните конфигурации своей среды (по крайней мере, идентификатор клиента Terraform и секрет), для передачи их провайдеру keycloak.
Файл terragrunt-local.hcl похож на terragrunt.hcl, за исключением конфигурации удаленного состояния, которая в данном случае не нужна. Файл local в первую очередь предназначен для локального тестирования конфигурации.
Мы используем Docker Compose для запуска кластера Keycloak, что позволяет нам беспрепятственно запускать наши локальные конфигурации Terraform на нем.
version: '3'
volumes:
postgres_data:
driver: local
services:
postgres:
image: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
ports:
- "5432:5432"
keycloak:
image: quay.io/keycloak/keycloak:23.0.6
environment:
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: password
KC_DB_URL_HOST: postgres
KC_DB: postgres
KC_DB_SCHEMA: public
KC_HTTP_RELATIVE_PATH: /keycloak
KC_HOSTNAME_ADMIN: 127.0.0.1
KC_HOSTNAME: localhost
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
command:
- start-dev
ports:
- "8080:8080"
- "8787:8787"
depends_on:
- postgres
config_keycloak:
image: ubuntu
volumes:
- ./keycloak-docker-config.sh:/opt/keycloak-docker-config.sh
command: ./opt/keycloak-docker-config.sh
depends_on:
- keycloak
Скрипт keycloak-docker-config.sh в основном используется для настройки клиента с привилегиями админа, которые Terraform будет использовать во время своей работы.
#!/bin/bash
apt update -y && apt -y install jq curl
until $(curl --output /dev/null --silent --head --fail http://keycloak:8080/keycloak); do
printf '.'
sleep 5
done
# Get access token
TOKEN=$( \
curl -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=admin-cli" \
-d "username=admin" \
-d "password=admin" \
-d "grant_type=password" \
"http://keycloak:8080/keycloak/realms/master/protocol/openid-connect/token" | jq -r '.access_token')
# Create Terraform client (terraform/terraform)
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{"clientId": "terraform", "name": "terraform", "enabled": true, "publicClient": false, "secret": "terraform", "serviceAccountsEnabled": true}' \
"http://keycloak:8080/keycloak/admin/realms/master/clients"
# Get the Terraform service account user ID
USER_ID=$( \
curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
"http://keycloak:8080/keycloak/admin/realms/master/users?username=service-account-terraform" | jq -r '.[0].id')
# Get the admin role ID
ROLE_ID=$( \
curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
"http://keycloak:8080/keycloak/admin/realms/master/roles" | jq -r '.[] | select(.name == "admin") | .id')
# Add the admin role to the Terraform service account user
curl -kv -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '[{"id":"'"${ROLE_ID}"'", "name":"admin"}]' \
"http://keycloak:8080/keycloak/admin/realms/master/users/$USER_ID/role-mappings/realm"
Чтобы запустить его, откройте terminal и выполните следующую команду docker compose:
docker-compose up --build
После того, как контейнеры docker-compose будут запущены, перейдите на http://localhost:8080/keycloak и войдите в систему, используя учетные данные admin/admin. Убедитесь, что клиент Terraform настроен в пределах главной области.
Теперь пришло время запустить ваши локальные конфигурации Terraform. Откройте терминал и выполните следующие команды:
# Navigate to the local environment
$ cd local
# Ensure that Terraform-related files, including the auto-generated backend.tf and provider.tf, are removed
$ rm -r backend.tf provider.tf terraform.tfstate terraform.tfstate.backup .terraform.lock.hcl .terraform
# Initialize Terraform to create all necessary files
$ terragrunt init --terragrunt-config terragrunt-local.hcl
# Apply the Terraform configurations
$ terragrunt apply --terragrunt-config terragrunt-local.hcl
Управление конфигурациями Keycloak с помощью Terraform может значительно упростить процесс разработки. Следуя шагам, описанным в этом руководстве, вы сможете настраивать и поддерживать среды Keycloak, обеспечивая согласованность и масштабируемость в своих проектах.
Узнайте об услуге devops support и закажите звонок у наших менеджеров. Поможем с любой задачей
Узнать больше