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 OpenTofu 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.
text# add the nginx feature to all platform clustersAdd the nginx platform feature to all clusters# or optionally only add a feature to a single clusterAdd 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.
text# list all platform componentsgit ls-files '*_feature_*.tf'aks_gc0_westeurope_feature_nginx.tfeks_gc0_eu-west-1_feature_nginx.tfgke_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 OpenTofu syntax.
hclmodule "example" {providers = {kustomization = kustomization}# kustomization overlay module, use the framework version# that all other modules in your repository usesource = "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 nullcommon_annotations = {"example-annotation" = var.example_annotation}# set labels on all Kubernetes resources# (optional), defaults to nullcommon_labels = {"example-label" = var.example_label}# generate Kubernetes configMaps# (optional), defaults to nullconfig_map_generator = [{# name (required)# Sets 'metadata.name' of the configMap resourcename = "example"# namespace (required)# Sets 'metadata.namespace' of the configMap resourcenamespace = "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 nullsecret_generator = [{# name (required)# Sets 'metadata.name' of the secret resourcename = "example"# namespace (required)# Sets 'metadata.namespace' of the secret resourcenamespace = "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 nullgenerator_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 nullimages = [{# 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 nullname_prefix = "prefix-"name_suffix = "-suffix"# namespace to set for all resources# (optional), default to nullnamespace = "example"# patches to apply to resources# (optional), defaults to nullpatches = [{# 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: replacepath: /metadata/namevalue: newnameEOF# 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 nullreplicas = [{# Refers to the 'metadata.name' of the resource to scalename = "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 OpenTofu 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.