Platform Features

TL;DR:

  • Platform feature modules provision Kubernetes resources on clusters provisioned using cluster modules.
  • Consider platform feature modules for anything that's required before deploying application workloads.
  • Kubernetes resources managed by platform feature modules are fully integrated into the Terraform lifecycle.
  • Your agent scaffolds platform features from upstream Helm charts or YAML manifests following the Kubestack skill.

Adding or Removing Platform Features

Platform features can be added or removed by adding or removing feature modules and their cluster bindings. The easiest way to do so is to ask your AI coding agent that has learned the Kubestack skill to scaffold the module for you.

Following the skill, your agent only makes changes to local files, and you can see the changes with git status. To have the changes take effect, you have to commit, push, merge and promote them following the GitOps flow.

Adding a Platform Feature

Adding a platform feature adds a module directory modules/<feature_name>/ and one binding file per cluster to your repository. Ask your agent to scaffold the feature for you. Your agent researches the upstream source, renders it using helm template for Helm charts or fetches the upstream manifest for plain YAML, and configures the provider and environments of the new feature to match the cluster it is added to automatically.

# add the nginx feature to all platform clusters
Add the nginx platform feature to all clusters
# or optionally only add a feature to a single cluster
Add the nginx platform feature to the eks_gc0_eu-west-1 cluster

Removing a Platform Feature

You can also ask your agent to remove a platform feature for you.

# list all platform components
git ls-files '*_feature_*.tf'
aks_gc0_westeurope_feature_nginx.tf
eks_gc0_eu-west-1_feature_nginx.tf
gke_gc0_europe-west1_feature_nginx.tf
# then ask your agent to remove the desired feature by <name>
Remove the nginx platform feature from the gke_gc0_europe-west1 cluster

Configuration

Platform feature modules call the framework's kustomization overlay module. The overlay provides the same attributes available in a kustomization.yaml. See the commenteded examples below for more details and how to use them inside Terraform syntax.

module "example" {
providers = {
kustomization = kustomization
}
# kustomization overlay module, use the framework version
# that all other modules in your repository use
source = "github.com/kbst/terraform-kubestack//kustomization/overlay?ref=<version>"
configuration = {
apps = {
# list of paths to YAML files or Kustomizations to deploy
# (required)
resources = [
"${path.module}/manifests/upstream.yaml"
]
# set annotations on all Kubernetes resources
# (optional), defaults to null
common_annotations = {
"example-annotation" = var.example_annotation
}
# set labels on all Kubernetes resources
# (optional), defaults to null
common_labels = {
"example-label" = var.example_label
}
# generate Kubernetes configMaps
# (optional), defaults to null
config_map_generator = [{
# name (required)
# Sets 'metadata.name' of the configMap resource
name = "example"
# namespace (required)
# Sets 'metadata.namespace' of the configMap resource
namespace = "example"
# behavior (optional)
# Valid values: 'create', 'replace' or 'merge'. Defaults to 'create'.
behavior = "create"
# literals (optional)
# List of 'KEY=VALUE' strings. Sets 'data[KEY] = VALUE' in the configMap.
literals = [
"KEY=VALUE"
]
# envs (optional)
# List of paths (strings) to env files (one KEY=VALUE pair per line).
# Sets 'data[KEY] = VALUE' in the configMap per line in the env file.
envs = [
"${path.module}/manifests/env"
]
# files (optional)
# List of paths (strings) to files.
# Sets 'data[KEY] = file_content'. KEY defaults to the file's name.
# Overwrite by prefixing 'customkey='.
files = [
"${path.module}/manifests/cfg.ini" # data["cfg.ini"] = file_content
"prod.ini=${path.module}/manifests/cfg.ini" # data["prod.ini"] = file_content
]
# options (optional)
# Same as top level 'generator_options' but specific to this configMap.
options = {
# see generator_options
}
}]
# generate Kubernetes secrets
# (optional), defaults to null
secret_generator = [{
# name (required)
# Sets 'metadata.name' of the secret resource
name = "example"
# namespace (required)
# Sets 'metadata.namespace' of the secret resource
namespace = "example"
# behavior (optional)
# Valid values: 'create', 'replace' or 'merge'. Defaults to 'create'.
behavior = "create"
# type (optional)
# 'type' attribute of the secret to generate.
type = "generic"
# literals (optional)
# List of 'KEY=VALUE' strings. Sets 'data[KEY] = VALUE' in the secret.
literals = [
"KEY=VALUE"
]
# envs (optional)
# List of paths (strings) to env files (one KEY=VALUE pair per line).
# Sets 'data[KEY] = VALUE' in the secret per line in the env file.
envs = [
"${path.module}/manifests/env"
]
# files (optional)
# List of paths (strings) to files.
# Sets 'data[KEY] = file_content'. KEY defaults to the file's name.
# Overwrite by prefixing 'customkey='.
files = [
"${path.module}/manifests/cfg.ini" # data["cfg.ini"] = file_content
"prod.ini=${path.module}/manifests/cfg.ini" # data["prod.ini"] = file_content
]
# options (optional)
# Same as top level 'generator_options' but specific to this secret.
options = {
# see generator_options
}
}]
# set options for all configMap and secret generators
# (optional), defaults to null
generator_options = {
# annotations (optional)
# Sets 'metadata.annotations' on the generated resources. Defaults to '{}'.
annotations = {
example-annotation = "example"
}
# labels (optional)
# Sets 'metadata.labels' on the generated resources. Defaults to '{}'.
labels = {
example-label = "example"
}
# disable_name_suffix_hash (optional)
# Disables hash suffix of generated resource's 'metadata.name'.
# Defaults to 'false'.
disable_name_suffix_hash = true
}
# patch image names, tags or digests
# (optional), defaults to null
images = [{
# Refers to the 'pod.spec.container.name' to modify the 'image' attribute of.
name = "busybox"
# Customize the 'registry/name' part of the image. The part before the ':'
new_name = "new_name"
# Customize the 'tag' part of the image. The part after the ':'.
new_tag = "new_tag"
# Replace the 'tag' part of an image with a 'digest'.
digest = "sha256:..."
}]
# prefix or suffix to add to resource names
# (optional), default to null
name_prefix = "prefix-"
name_suffix = "-suffix"
# namespace to set for all resources
# (optional), default to null
namespace = "example"
# patches to apply to resources
# (optional), defaults to null
patches = [{
# path (optional)
# Path to a file that defines a strategic merge or JSON patch.
path = "${path.module}/manifests/patch.yaml"
# patch (optional)
# Inline string that defines a strategic merge or JSON patch.
patch = <<-EOF
- op: replace
path: /metadata/name
value: newname
EOF
# target (optional)
# Target one or multiple resources to be patched.
target = {
group = ""
version = "v1"
kind = "ConfigMap"
name = "example"
namespace = "example"
label_selector = "key=value"
annotation_selector = "key=value"
}
}]
# set replicas attribute of deployments and similar resources
# (optional), defaults to null
replicas = [{
# Refers to the 'metadata.name' of the resource to scale
name = "example"
# Sets the desired number of replicas.
count = 5
}]
}
ops = {}
}
}

Low-level arguments

In addition to the convenience kustomization attributes documented above, platform feature modules also pass the following low-level attributes through to the kustomization provider. These Kustomization attributes are less useful in the Terraform context and as such are not documented here.

  • components (optional) List of paths to Kustomize components.
  • crds (optional) List of paths to Kustomize CRDs.
  • generators (optional) List of paths to Kustomize generators.
  • transformers (optional) List of paths to Kustomize transformers.
  • vars (optional) List of objects to define Kustomize vars.