From 10966c792a79d00e57fbc104c120c4585e0239bc Mon Sep 17 00:00:00 2001 From: Mauritz Uphoff Date: Wed, 15 Apr 2026 10:35:57 +0200 Subject: [PATCH] chore(examples): add new examples Signed-off-by: Mauritz Uphoff --- examples/iaas-ha-vrrp/MAINTAINERS.md | 2 +- .../.terraform.lock.hcl | 0 .../00-provider.tf | 0 .../01-variables.tf | 0 .../02-folder.tf | 0 .../MAINTAINERS.md | 2 +- .../README.md | 0 .../s3-aws-terraform-provider/MAINTAINERS.md | 9 + examples/s3-aws-terraform-provider/README.md | 5 + examples/s3-aws-terraform-provider/main.tf | 77 ++++++++ .../MAINTAINERS.md | 9 + .../README.md | 6 + .../main.tf | 60 ++++++ examples/ske-encrypted-volumes/MAINTAINERS.md | 9 + examples/ske-encrypted-volumes/README.md | 5 + examples/ske-encrypted-volumes/main.tf | 170 +++++++++++++++++ .../ske-external-secrets-sync/MAINTAINERS.md | 2 +- .../MAINTAINERS.md | 9 + .../README.md | 5 + .../ske-kubernetes-terraform-provider/main.tf | 76 ++++++++ examples/ske-nginx-rate-limit/MAINTAINERS.md | 2 +- .../MAINTAINERS.md | 9 + .../README.md | 5 + .../main.tf | 175 ++++++++++++++++++ .../prom-values.tftpl | 57 ++++++ .../MAINTAINERS.md | 9 + .../ske-observability-log-alerts/README.md | 5 + examples/ske-observability-log-alerts/main.tf | 175 ++++++++++++++++++ 28 files changed, 879 insertions(+), 4 deletions(-) rename examples/{nested-folders => resourcemanager-nested-folders}/.terraform.lock.hcl (100%) rename examples/{nested-folders => resourcemanager-nested-folders}/00-provider.tf (100%) rename examples/{nested-folders => resourcemanager-nested-folders}/01-variables.tf (100%) rename examples/{nested-folders => resourcemanager-nested-folders}/02-folder.tf (100%) rename examples/{nested-folders => resourcemanager-nested-folders}/MAINTAINERS.md (64%) rename examples/{nested-folders => resourcemanager-nested-folders}/README.md (100%) create mode 100644 examples/s3-aws-terraform-provider/MAINTAINERS.md create mode 100644 examples/s3-aws-terraform-provider/README.md create mode 100644 examples/s3-aws-terraform-provider/main.tf create mode 100644 examples/secretsmanager-vault-terraform-provider/MAINTAINERS.md create mode 100644 examples/secretsmanager-vault-terraform-provider/README.md create mode 100644 examples/secretsmanager-vault-terraform-provider/main.tf create mode 100644 examples/ske-encrypted-volumes/MAINTAINERS.md create mode 100644 examples/ske-encrypted-volumes/README.md create mode 100644 examples/ske-encrypted-volumes/main.tf create mode 100644 examples/ske-kubernetes-terraform-provider/MAINTAINERS.md create mode 100644 examples/ske-kubernetes-terraform-provider/README.md create mode 100644 examples/ske-kubernetes-terraform-provider/main.tf create mode 100644 examples/ske-observability-alerting-kube-state-metrics/MAINTAINERS.md create mode 100644 examples/ske-observability-alerting-kube-state-metrics/README.md create mode 100644 examples/ske-observability-alerting-kube-state-metrics/main.tf create mode 100644 examples/ske-observability-alerting-kube-state-metrics/prom-values.tftpl create mode 100644 examples/ske-observability-log-alerts/MAINTAINERS.md create mode 100644 examples/ske-observability-log-alerts/README.md create mode 100644 examples/ske-observability-log-alerts/main.tf diff --git a/examples/iaas-ha-vrrp/MAINTAINERS.md b/examples/iaas-ha-vrrp/MAINTAINERS.md index dadc483..1aaefce 100644 --- a/examples/iaas-ha-vrrp/MAINTAINERS.md +++ b/examples/iaas-ha-vrrp/MAINTAINERS.md @@ -4,6 +4,6 @@ General maintainers: - Mauritz Uphoff (mauritz.uphoff@digits.schwarz) -This BP is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. +This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. For questions, issues, or feature requests, please email general maintainers. Please include the BP name and version in your request. We will track your request as an issue. diff --git a/examples/nested-folders/.terraform.lock.hcl b/examples/resourcemanager-nested-folders/.terraform.lock.hcl similarity index 100% rename from examples/nested-folders/.terraform.lock.hcl rename to examples/resourcemanager-nested-folders/.terraform.lock.hcl diff --git a/examples/nested-folders/00-provider.tf b/examples/resourcemanager-nested-folders/00-provider.tf similarity index 100% rename from examples/nested-folders/00-provider.tf rename to examples/resourcemanager-nested-folders/00-provider.tf diff --git a/examples/nested-folders/01-variables.tf b/examples/resourcemanager-nested-folders/01-variables.tf similarity index 100% rename from examples/nested-folders/01-variables.tf rename to examples/resourcemanager-nested-folders/01-variables.tf diff --git a/examples/nested-folders/02-folder.tf b/examples/resourcemanager-nested-folders/02-folder.tf similarity index 100% rename from examples/nested-folders/02-folder.tf rename to examples/resourcemanager-nested-folders/02-folder.tf diff --git a/examples/nested-folders/MAINTAINERS.md b/examples/resourcemanager-nested-folders/MAINTAINERS.md similarity index 64% rename from examples/nested-folders/MAINTAINERS.md rename to examples/resourcemanager-nested-folders/MAINTAINERS.md index dadc483..1aaefce 100644 --- a/examples/nested-folders/MAINTAINERS.md +++ b/examples/resourcemanager-nested-folders/MAINTAINERS.md @@ -4,6 +4,6 @@ General maintainers: - Mauritz Uphoff (mauritz.uphoff@digits.schwarz) -This BP is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. +This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. For questions, issues, or feature requests, please email general maintainers. Please include the BP name and version in your request. We will track your request as an issue. diff --git a/examples/nested-folders/README.md b/examples/resourcemanager-nested-folders/README.md similarity index 100% rename from examples/nested-folders/README.md rename to examples/resourcemanager-nested-folders/README.md diff --git a/examples/s3-aws-terraform-provider/MAINTAINERS.md b/examples/s3-aws-terraform-provider/MAINTAINERS.md new file mode 100644 index 0000000..1aaefce --- /dev/null +++ b/examples/s3-aws-terraform-provider/MAINTAINERS.md @@ -0,0 +1,9 @@ +# Maintainers + +General maintainers: + +- Mauritz Uphoff (mauritz.uphoff@digits.schwarz) + +This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. +For questions, issues, or feature requests, please email general maintainers. +Please include the BP name and version in your request. We will track your request as an issue. diff --git a/examples/s3-aws-terraform-provider/README.md b/examples/s3-aws-terraform-provider/README.md new file mode 100644 index 0000000..a91cda7 --- /dev/null +++ b/examples/s3-aws-terraform-provider/README.md @@ -0,0 +1,5 @@ +# Terraform AWS Provider S3 Integration + +## Overview + +Demonstrates how to use the HashiCorp `aws` provider to interact with STACKIT's S3-compatible Object Storage. diff --git a/examples/s3-aws-terraform-provider/main.tf b/examples/s3-aws-terraform-provider/main.tf new file mode 100644 index 0000000..6db7d30 --- /dev/null +++ b/examples/s3-aws-terraform-provider/main.tf @@ -0,0 +1,77 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +terraform { + required_providers { + stackit = { + source = "stackitcloud/stackit" + version = "> 0.90" + } + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} + +variable "project_id" { + description = "The STACKIT Project ID where the Object Storage will be created" + type = string +} + +provider "stackit" { + default_region = "eu01" + service_account_key_path = "" +} + +resource "stackit_objectstorage_bucket" "example" { + project_id = var.project_id + name = "my-stackit-s3-bucket" +} + +resource "stackit_objectstorage_credentials_group" "example" { + project_id = var.project_id + name = "my-credentials-group" +} + +resource "stackit_objectstorage_credential" "example" { + project_id = var.project_id + credentials_group_id = stackit_objectstorage_credentials_group.example.credentials_group_id +} + +provider "aws" { + region = "eu01" + access_key = stackit_objectstorage_credential.example.access_key + secret_key = stackit_objectstorage_credential.example.secret_key + + # These flags are mandatory when connecting to a custom S3-compatible backend + skip_credentials_validation = true + skip_region_validation = true + skip_requesting_account_id = true + skip_metadata_api_check = true + s3_use_path_style = true + + # STACKIT S3 Endpoint + endpoints { + s3 = "https://object.storage.eu01.onstackit.cloud" + } +} + +resource "aws_s3_object" "example_file" { + depends_on = [stackit_objectstorage_bucket.example] + + bucket = stackit_objectstorage_bucket.example.name + key = "hello-world.txt" + content = "Hello from STACKIT Object Storage managed via the AWS Terraform Provider!" +} diff --git a/examples/secretsmanager-vault-terraform-provider/MAINTAINERS.md b/examples/secretsmanager-vault-terraform-provider/MAINTAINERS.md new file mode 100644 index 0000000..1aaefce --- /dev/null +++ b/examples/secretsmanager-vault-terraform-provider/MAINTAINERS.md @@ -0,0 +1,9 @@ +# Maintainers + +General maintainers: + +- Mauritz Uphoff (mauritz.uphoff@digits.schwarz) + +This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. +For questions, issues, or feature requests, please email general maintainers. +Please include the BP name and version in your request. We will track your request as an issue. diff --git a/examples/secretsmanager-vault-terraform-provider/README.md b/examples/secretsmanager-vault-terraform-provider/README.md new file mode 100644 index 0000000..6985850 --- /dev/null +++ b/examples/secretsmanager-vault-terraform-provider/README.md @@ -0,0 +1,6 @@ +# # STACKIT Secrets Manager Vault Provider Integration + +## Overview + +This guide outlines the process of utilizing the [HashiCorp Vault provider](https://registry.terraform.io/providers/hashicorp/vault) +alongside the STACKIT provider to write secrets in the STACKIT Secrets Manager. diff --git a/examples/secretsmanager-vault-terraform-provider/main.tf b/examples/secretsmanager-vault-terraform-provider/main.tf new file mode 100644 index 0000000..ddd4b6e --- /dev/null +++ b/examples/secretsmanager-vault-terraform-provider/main.tf @@ -0,0 +1,60 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +provider "stackit" { + default_region = "eu01" + service_account_key_path = "" +} + +resource "stackit_secretsmanager_instance" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + name = "example-instance" +} + +resource "stackit_secretsmanager_user" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + instance_id = stackit_secretsmanager_instance.example.instance_id + description = "Example user" + write_enabled = true +} + +provider "vault" { + address = "https://prod.sm.eu01.stackit.cloud" + skip_child_token = true + + auth_login_userpass { + username = stackit_secretsmanager_user.example.username + password = stackit_secretsmanager_user.example.password + } +} + +resource "stackit_observability_instance" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + name = "example-instance" + plan_name = "Observability-Monitoring-Medium-EU01" +} + +resource "vault_kv_secret_v2" "example" { + mount = stackit_secretsmanager_instance.example.instance_id + name = "my-secret" + cas = 1 + delete_all_versions = true + + data_json = jsonencode( + { + grafana_password = stackit_observability_instance.example.grafana_initial_admin_password, + other_secret = "your-other-secret-value" + } + ) +} diff --git a/examples/ske-encrypted-volumes/MAINTAINERS.md b/examples/ske-encrypted-volumes/MAINTAINERS.md new file mode 100644 index 0000000..1aaefce --- /dev/null +++ b/examples/ske-encrypted-volumes/MAINTAINERS.md @@ -0,0 +1,9 @@ +# Maintainers + +General maintainers: + +- Mauritz Uphoff (mauritz.uphoff@digits.schwarz) + +This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. +For questions, issues, or feature requests, please email general maintainers. +Please include the BP name and version in your request. We will track your request as an issue. diff --git a/examples/ske-encrypted-volumes/README.md b/examples/ske-encrypted-volumes/README.md new file mode 100644 index 0000000..3fdfd40 --- /dev/null +++ b/examples/ske-encrypted-volumes/README.md @@ -0,0 +1,5 @@ +# Encrypted Volumes for SKE + +## Overview + +This guide demonstrates how to roll out an encrypted storage class for SKE using the STACKIT Key Management Service (KMS). To achieve this, we use a **Service Account Impersonation** (Act-As) pattern. This allows the internal SKE service account to perform encryption and decryption tasks on behalf of a user-managed service account that has been granted access to your KMS keys. diff --git a/examples/ske-encrypted-volumes/main.tf b/examples/ske-encrypted-volumes/main.tf new file mode 100644 index 0000000..8e2d010 --- /dev/null +++ b/examples/ske-encrypted-volumes/main.tf @@ -0,0 +1,170 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +provider "stackit" { + default_region = "eu01" + service_account_key_path = "" +} + +provider "kubernetes" { + host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server + client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data) + client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data) + cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data) +} + +resource "stackit_ske_cluster" "default" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + name = "ske-enc-vol" + kubernetes_version_min = "1.33" + + node_pools = [{ + name = "standard" + machine_type = "c2i.4" + minimum = 1 + maximum = 3 + availability_zones = ["eu01-1"] + os_name = "flatcar" + volume_size = 32 + }] +} + +resource "stackit_ske_kubeconfig" "default" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + cluster_name = stackit_ske_cluster.default.name + refresh = true +} + +# ------------------------------------------------------------------------ +# 2. Identify the Internal SKE Service Account +# ------------------------------------------------------------------------ +data "stackit_service_accounts" "ske_internal" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + email_suffix = "@ske.sa.stackit.cloud" + + depends_on = [stackit_ske_cluster.default] +} + +# ------------------------------------------------------------------------ +# 3. Setup KMS Infrastructure +# ------------------------------------------------------------------------ +resource "stackit_kms_keyring" "encryption" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + display_name = "ske-volume-keyring" +} + +resource "stackit_kms_key" "volume_key" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + keyring_id = stackit_kms_keyring.encryption.keyring_id + display_name = "volume-encryption-key" + protection = "software" + algorithm = "aes_256_gcm" + purpose = "symmetric_encrypt_decrypt" +} + +# ------------------------------------------------------------------------ +# 4. Configure Identity and Permissions (Act-As) +# ------------------------------------------------------------------------ +# Create the service account that 'owns' the KMS access +resource "stackit_service_account" "kms_manager" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + name = "volume-encryptor" +} + +# Grant the 'kms.admin' role to the manager service-account +resource "stackit_authorization_project_role_assignment" "kms_user" { + // in this case the STACKIT project_id + resource_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + role = "kms.admin" + subject = stackit_service_account.kms_manager.email +} + +# Authorize the internal SKE account to impersonate the kms manager service-account (Act-As) +resource "stackit_authorization_service_account_role_assignment" "ske_impersonation" { + resource_id = stackit_service_account.kms_manager.service_account_id + role = "user" + subject = data.stackit_service_accounts.ske_internal.items[0].email +} + +resource "kubernetes_storage_class_v1" "encrypted_premium" { + metadata { + name = "stackit-encrypted-premium" + } + + storage_provisioner = "block-storage.csi.stackit.cloud" + reclaim_policy = "Delete" + allow_volume_expansion = true + volume_binding_mode = "WaitForFirstConsumer" + + parameters = { + type = "storage_premium_perf6" + encrypted = "true" + kmsKeyID = stackit_kms_key.volume_key.key_id + kmsKeyringID = stackit_kms_keyring.encryption.keyring_id + kmsProjectID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + kmsKeyVersion = "1" + kmsServiceAccount = stackit_service_account.kms_manager.email + } + + depends_on = [ + stackit_authorization_service_account_role_assignment.ske_impersonation, + stackit_authorization_project_role_assignment.kms_user + ] +} + +resource "kubernetes_persistent_volume_claim_v1" "test_pvc" { + metadata { + name = "test-encryption-pvc" + } + + spec { + access_modes = ["ReadWriteOnce"] + + resources { + requests = { + storage = "10Gi" + } + } + + storage_class_name = kubernetes_storage_class_v1.encrypted_premium.metadata[0].name + } +} + +# ------------------------------------------------------------------------ +# 7. Create a Pod to Consume the Volume +# ------------------------------------------------------------------------ +resource "kubernetes_pod_v1" "test_app" { + metadata { + name = "encrypted-volume-test" + } + + spec { + container { + image = "nginx:latest" + name = "web-server" + + volume_mount { + mount_path = "/usr/share/nginx/html" + name = "data-volume" + } + } + + volume { + name = "data-volume" + persistent_volume_claim { + claim_name = "test-encryption-pvc" + } + } + } +} diff --git a/examples/ske-external-secrets-sync/MAINTAINERS.md b/examples/ske-external-secrets-sync/MAINTAINERS.md index dadc483..1aaefce 100644 --- a/examples/ske-external-secrets-sync/MAINTAINERS.md +++ b/examples/ske-external-secrets-sync/MAINTAINERS.md @@ -4,6 +4,6 @@ General maintainers: - Mauritz Uphoff (mauritz.uphoff@digits.schwarz) -This BP is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. +This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. For questions, issues, or feature requests, please email general maintainers. Please include the BP name and version in your request. We will track your request as an issue. diff --git a/examples/ske-kubernetes-terraform-provider/MAINTAINERS.md b/examples/ske-kubernetes-terraform-provider/MAINTAINERS.md new file mode 100644 index 0000000..1aaefce --- /dev/null +++ b/examples/ske-kubernetes-terraform-provider/MAINTAINERS.md @@ -0,0 +1,9 @@ +# Maintainers + +General maintainers: + +- Mauritz Uphoff (mauritz.uphoff@digits.schwarz) + +This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. +For questions, issues, or feature requests, please email general maintainers. +Please include the BP name and version in your request. We will track your request as an issue. diff --git a/examples/ske-kubernetes-terraform-provider/README.md b/examples/ske-kubernetes-terraform-provider/README.md new file mode 100644 index 0000000..2fe6535 --- /dev/null +++ b/examples/ske-kubernetes-terraform-provider/README.md @@ -0,0 +1,5 @@ +# Terraform SKE Kubernetes Provider Integration + +## Overview + +Demonstrates how to use the HashiCorp `kubernetes` provider to manage resources inside a SKE cluster. diff --git a/examples/ske-kubernetes-terraform-provider/main.tf b/examples/ske-kubernetes-terraform-provider/main.tf new file mode 100644 index 0000000..6480f5e --- /dev/null +++ b/examples/ske-kubernetes-terraform-provider/main.tf @@ -0,0 +1,76 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +terraform { + required_providers { + stackit = { + source = "stackitcloud/stackit" + version = "~> 0.35" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.24" + } + } +} + +variable "project_id" { + description = "The STACKIT Project ID" + type = string +} + +provider "stackit" { + default_region = "eu01" + service_account_key_path = "" +} + +resource "stackit_ske_cluster" "example" { + project_id = var.project_id + name = "example" + kubernetes_version_min = "1.33" + + node_pools = [ + { + name = "example-node-pool" + machine_type = "g2i.4" + minimum = 1 + maximum = 2 + availability_zones = ["eu01-1"] + os_version_min = "3815.2.5" + os_name = "flatcar" + volume_size = 32 + volume_type = "storage_premium_perf6" + } + ] +} + + +resource "stackit_ske_kubeconfig" "example" { + project_id = var.project_id + cluster_name = stackit_ske_cluster.example.name + expiration = 3600 +} + +provider "kubernetes" { + host = yamldecode(stackit_ske_kubeconfig.ske_kubeconfig_01.kube_config).clusters[0].cluster.server + client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.ske_kubeconfig_01.kube_config).users[0].user["client-certificate-data"]) + client_key = base64decode(yamldecode(stackit_ske_kubeconfig.ske_kubeconfig_01.kube_config).users[0].user["client-key-data"]) + cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.ske_kubeconfig_01.kube_config).clusters[0].cluster["certificate-authority-data"]) +} + +resource "kubernetes_namespace" "example" { + metadata { + name = "stackit-demo-namespace" + } +} diff --git a/examples/ske-nginx-rate-limit/MAINTAINERS.md b/examples/ske-nginx-rate-limit/MAINTAINERS.md index dadc483..1aaefce 100644 --- a/examples/ske-nginx-rate-limit/MAINTAINERS.md +++ b/examples/ske-nginx-rate-limit/MAINTAINERS.md @@ -4,6 +4,6 @@ General maintainers: - Mauritz Uphoff (mauritz.uphoff@digits.schwarz) -This BP is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. +This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. For questions, issues, or feature requests, please email general maintainers. Please include the BP name and version in your request. We will track your request as an issue. diff --git a/examples/ske-observability-alerting-kube-state-metrics/MAINTAINERS.md b/examples/ske-observability-alerting-kube-state-metrics/MAINTAINERS.md new file mode 100644 index 0000000..1aaefce --- /dev/null +++ b/examples/ske-observability-alerting-kube-state-metrics/MAINTAINERS.md @@ -0,0 +1,9 @@ +# Maintainers + +General maintainers: + +- Mauritz Uphoff (mauritz.uphoff@digits.schwarz) + +This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. +For questions, issues, or feature requests, please email general maintainers. +Please include the BP name and version in your request. We will track your request as an issue. diff --git a/examples/ske-observability-alerting-kube-state-metrics/README.md b/examples/ske-observability-alerting-kube-state-metrics/README.md new file mode 100644 index 0000000..d4636e0 --- /dev/null +++ b/examples/ske-observability-alerting-kube-state-metrics/README.md @@ -0,0 +1,5 @@ +# SKE Observability alerting with Kube-State-Metrics + +## Overview + +This guide explains how to configure the STACKIT Observability product to send alerts using metrics gathered from kube-state-metrics. diff --git a/examples/ske-observability-alerting-kube-state-metrics/main.tf b/examples/ske-observability-alerting-kube-state-metrics/main.tf new file mode 100644 index 0000000..806856a --- /dev/null +++ b/examples/ske-observability-alerting-kube-state-metrics/main.tf @@ -0,0 +1,175 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +provider "stackit" { + default_region = "eu01" + service_account_key_path = "" +} + +provider "kubernetes" { + host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server + client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data) + client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data) + cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data) +} + +provider "helm" { + kubernetes { + host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server + client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data) + client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data) + cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data) + } +} + +resource "stackit_ske_cluster" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + name = "example" + kubernetes_version_min = "1.31" + node_pools = [ + { + name = "standard" + machine_type = "c1.4" + minimum = "3" + maximum = "9" + max_surge = "3" + availability_zones = ["eu01-1", "eu01-2", "eu01-3"] + os_version_min = "4081.2.1" + os_name = "flatcar" + volume_size = 32 + volume_type = "storage_premium_perf6" + } + ] + maintenance = { + enable_kubernetes_version_updates = true + enable_machine_image_version_updates = true + start = "01:00:00Z" + end = "02:00:00Z" + } +} + +resource "stackit_ske_kubeconfig" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + cluster_name = stackit_ske_cluster.example.name + refresh = true +} + +locals { + alert_config = { + route = { + receiver = "EmailStackit", + repeat_interval = "1m", + continue = true + } + receivers = [ + { + name = "EmailStackit", + email_configs = [ + { + to = "" # Replace with your actual email + } + ] + } + ] + } +} + +resource "stackit_observability_instance" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + name = "example" + plan_name = "Observability-Large-EU01" + alert_config = local.alert_config +} + +resource "stackit_observability_credential" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + instance_id = stackit_observability_instance.example.instance_id +} + +resource "kubernetes_namespace" "monitoring" { + metadata { + name = "monitoring" + } +} + +resource "kubernetes_secret" "argus_prometheus_authorization" { + metadata { + name = "argus-prometheus-credentials" + namespace = kubernetes_namespace.monitoring.metadata[0].name + } + + data = { + username = stackit_observability_credential.example.username + password = stackit_observability_credential.example.password + } +} + +resource "helm_release" "prometheus_operator" { + name = "prometheus-operator" + repository = "https://prometheus-community.github.io/helm-charts" + chart = "kube-prometheus-stack" + version = "60.1.0" + namespace = kubernetes_namespace.monitoring.metadata[0].name + + values = [ + templatefile("prom-values.tftpl", { + metrics_push_url = stackit_observability_instance.example.metrics_push_url + secret_name = kubernetes_secret.argus_prometheus_authorization.metadata[0].name + }) + ] +} + +resource "stackit_observability_alertgroup" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + instance_id = stackit_observability_instance.example.instance_id + name = "TestAlertGroup" + interval = "2h" + rules = [ + { + alert = "SimplePodCheck" + expression = "sum(kube_pod_status_phase{phase=\"Running\", namespace=\"example\"}) > 0" + for = "60s" + labels = { + severity = "critical" + }, + annotations = { + summary = "Test Alert is working" + description = "Test Alert" + } + }, + ] +} + +resource "kubernetes_namespace" "example" { + metadata { + name = "example" + } +} + +resource "kubernetes_pod" "example" { + metadata { + name = "nginx" + namespace = kubernetes_namespace.example.metadata[0].name + labels = { + app = "nginx" + } + } + + spec { + container { + image = "nginx:latest" + name = "nginx" + } + } +} diff --git a/examples/ske-observability-alerting-kube-state-metrics/prom-values.tftpl b/examples/ske-observability-alerting-kube-state-metrics/prom-values.tftpl new file mode 100644 index 0000000..4023033 --- /dev/null +++ b/examples/ske-observability-alerting-kube-state-metrics/prom-values.tftpl @@ -0,0 +1,57 @@ +prometheus: + enabled: true + agentMode: true + prometheusSpec: + enableRemoteWriteReceiver: true + scrapeInterval: 60s + evaluationInterval: 60s + replicas: 1 + storageSpec: + volumeClaimTemplate: + spec: + storageClassName: premium-perf4-stackit + accessModes: ['ReadWriteOnce'] + resources: + requests: + storage: 80Gi + remoteWrite: + - url: ${metrics_push_url} + queueConfig: + batchSendDeadline: '5s' + # both values need to be configured according to your observability plan + capacity: 30000 + maxSamplesPerSend: 3000 + writeRelabelConfigs: + - sourceLabels: ['__name__'] + regex: 'apiserver_.*|etcd_.*|prober_.*|storage_.*|workqueue_(work|queue)_duration_seconds_bucket|kube_pod_tolerations|kubelet_.*|kubernetes_feature_enabled|instance_scrape_target_status' + action: 'drop' + - sourceLabels: ['namespace'] + regex: 'example' + action: 'keep' + basicAuth: + username: + key: username + name: ${secret_name} + password: + key: password + name: ${secret_name} + +grafana: + enabled: false + +defaultRules: + create: false + +alertmanager: + enabled: false + +nodeExporter: + enabled: true + +kube-state-metrics: + enabled: true + customResourceState: + enabled: true + collectors: + - deployments + - pods diff --git a/examples/ske-observability-log-alerts/MAINTAINERS.md b/examples/ske-observability-log-alerts/MAINTAINERS.md new file mode 100644 index 0000000..1aaefce --- /dev/null +++ b/examples/ske-observability-log-alerts/MAINTAINERS.md @@ -0,0 +1,9 @@ +# Maintainers + +General maintainers: + +- Mauritz Uphoff (mauritz.uphoff@digits.schwarz) + +This example is actively maintained. The owner is responsible for reviewing and updating dependencies and functionalities on a monthly basis. +For questions, issues, or feature requests, please email general maintainers. +Please include the BP name and version in your request. We will track your request as an issue. diff --git a/examples/ske-observability-log-alerts/README.md b/examples/ske-observability-log-alerts/README.md new file mode 100644 index 0000000..072cd49 --- /dev/null +++ b/examples/ske-observability-log-alerts/README.md @@ -0,0 +1,5 @@ +# # SKE Observability Log-Alerts + +## Overview + +This guide walks you through setting up log-based alerting in STACKIT Observability using Promtail to ship Kubernetes logs. diff --git a/examples/ske-observability-log-alerts/main.tf b/examples/ske-observability-log-alerts/main.tf new file mode 100644 index 0000000..1261cf4 --- /dev/null +++ b/examples/ske-observability-log-alerts/main.tf @@ -0,0 +1,175 @@ +# Copyright 2026 Schwarz Digits Cloud GmbH & Co. KG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +provider "stackit" { + default_region = "eu01" + service_account_key_path = "" +} + +provider "kubernetes" { + host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server + client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data) + client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data) + cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data) +} + +provider "helm" { + kubernetes { + host = yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.server + client_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-certificate-data) + client_key = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).users.0.user.client-key-data) + cluster_ca_certificate = base64decode(yamldecode(stackit_ske_kubeconfig.example.kube_config).clusters.0.cluster.certificate-authority-data) + } +} + +resource "stackit_ske_cluster" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + name = "example" + kubernetes_version_min = "1.31" + node_pools = [ + { + name = "standard" + machine_type = "c1.4" + minimum = "3" + maximum = "9" + max_surge = "3" + availability_zones = ["eu01-1", "eu01-2", "eu01-3"] + os_version_min = "4081.2.1" + os_name = "flatcar" + volume_size = 32 + volume_type = "storage_premium_perf6" + } + ] + maintenance = { + enable_kubernetes_version_updates = true + enable_machine_image_version_updates = true + start = "01:00:00Z" + end = "02:00:00Z" + } +} + +resource "stackit_ske_kubeconfig" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + cluster_name = stackit_ske_cluster.example.name + refresh = true +} + +locals { + alert_config = { + route = { + receiver = "EmailStackit", + repeat_interval = "1m", + continue = true + } + receivers = [ + { + name = "EmailStackit", + email_configs = [ + { + to = "" # Replace with your actual email + } + ] + } + ] + } +} + +resource "stackit_observability_instance" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + name = "example" + plan_name = "Observability-Large-EU01" + alert_config = local.alert_config +} + +resource "stackit_observability_credential" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + instance_id = stackit_observability_instance.example.instance_id +} + +resource "kubernetes_namespace" "monitoring" { + metadata { + name = "monitoring" + } +} + +resource "helm_release" "promtail" { + name = "promtail" + repository = "https://grafana.github.io/helm-charts" + chart = "promtail" + namespace = kubernetes_namespace.monitoring.metadata.0.name + version = "6.16.4" + + values = [ + <<-EOF + config: + clients: + # To find the Loki push URL, navigate to the observability instance in the portal and select the API tab. + - url: "https://${stackit_observability_credential.example.username}:${stackit_observability_credential.example.password}@/instances/${stackit_observability_instance.example.instance_id}/loki/api/v1/push" + EOF + ] +} + +resource "stackit_observability_logalertgroup" "example" { + project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + instance_id = stackit_observability_instance.example.instance_id + name = "TestLogAlertGroup" + interval = "1m" + rules = [ + { + alert = "SimplePodLogAlertCheck" + expression = "sum(rate({namespace=\"example\", pod=\"logger\"} |= \"Simulated error message\" [1m])) > 0" + for = "60s" + labels = { + severity = "critical" + }, + annotations = { + summary : "Test Log Alert is working" + description : "Test Log Alert" + }, + }, + ] +} + +resource "kubernetes_namespace" "example" { + metadata { + name = "example" + } +} + +resource "kubernetes_pod" "logger" { + metadata { + name = "logger" + namespace = kubernetes_namespace.example.metadata[0].name + labels = { + app = "logger" + } + } + + spec { + container { + name = "logger" + image = "bash" + command = [ + "bash", + "-c", + <&2 + done + EOF + ] + } + } +} -- 2.49.1