The kubernetes:yaml:ConfigGroup resource, part of the Pulumi Kubernetes provider, creates multiple Kubernetes resources from YAML manifests. A newer version is available as kubernetes.yaml/v2.ConfigGroup; this resource is maintained for backwards compatibility. This guide focuses on three capabilities: file and pattern-based loading, inline YAML strings, and runtime transformations.
ConfigGroup requires a configured Kubernetes cluster and access to YAML manifest files for file-based deployments. The examples are intentionally small. Combine them with your own manifests and cluster configuration.
Deploy resources from a single YAML file
Most deployments start with YAML manifests stored in version control, applying them to the cluster through ConfigGroup.
import * as k8s from "@pulumi/kubernetes";
const example = new k8s.yaml.ConfigGroup("example", {
files: "foo.yaml",
});
from pulumi_kubernetes.yaml import ConfigGroup
example = ConfigGroup(
"example",
files=["foo.yaml"],
)
package main
import (
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/yaml"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := yaml.NewConfigGroup(ctx, "example",
&yaml.ConfigGroupArgs{
Files: []string{"foo.yaml"},
},
)
if err != nil {
return err
}
return nil
})
}
using System.Threading.Tasks;
using Pulumi;
using Pulumi.Kubernetes.Yaml;
class YamlStack : Stack
{
public YamlStack()
{
var helloWorld = new ConfigGroup("example", new ConfigGroupArgs
{
Files = new[] { "foo.yaml" }
});
}
}
The files property accepts a path to a YAML file containing one or more Kubernetes resource definitions. ConfigGroup parses the file and creates each resource it finds.
Deploy all manifests matching a file pattern
When manifests are organized into directories, file patterns apply entire directories without listing each file individually.
import * as k8s from "@pulumi/kubernetes";
const example = new k8s.yaml.ConfigGroup("example", {
files: "yaml/*.yaml",
});
from pulumi_kubernetes.yaml import ConfigGroup
example = ConfigGroup(
"example",
files=["yaml/*.yaml"],
)
package main
import (
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/yaml"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := yaml.NewConfigGroup(ctx, "example",
&yaml.ConfigGroupArgs{
Files: []string{"yaml/*.yaml"},
},
)
if err != nil {
return err
}
return nil
})
}
using System.Threading.Tasks;
using Pulumi;
using Pulumi.Kubernetes.Yaml;
class YamlStack : Stack
{
public YamlStack()
{
var helloWorld = new ConfigGroup("example", new ConfigGroupArgs
{
Files = new[] { "yaml/*.yaml" }
});
}
}
The glob pattern yaml/*.yaml matches all YAML files in the yaml directory. ConfigGroup processes each matched file and creates the resources they define.
Define resources inline with YAML strings
For generated or templated resources, the yaml property accepts literal YAML strings instead of file references.
import * as k8s from "@pulumi/kubernetes";
const example = new k8s.yaml.ConfigGroup("example", {
yaml: `
apiVersion: v1
kind: Namespace
metadata:
name: foo
`,
})
from pulumi_kubernetes.yaml import ConfigGroup
example = ConfigGroup(
"example",
yaml=['''
apiVersion: v1
kind: Namespace
metadata:
name: foo
''']
)
package main
import (
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/yaml"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := yaml.NewConfigGroup(ctx, "example",
&yaml.ConfigGroupArgs{
YAML: []string{
`
apiVersion: v1
kind: Namespace
metadata:
name: foo
`,
},
})
if err != nil {
return err
}
return nil
})
}
using System.Threading.Tasks;
using Pulumi;
using Pulumi.Kubernetes.Yaml;
class YamlStack : Stack
{
public YamlStack()
{
var helloWorld = new ConfigGroup("example", new ConfigGroupArgs
{
Yaml = @"
apiVersion: v1
kind: Namespace
metadata:
name: foo
",
});
}
}
The yaml property takes a string containing valid Kubernetes YAML. This approach works well when manifests are generated programmatically or constructed from templates at deployment time.
Modify resources before deployment with transformations
Production deployments often need to adjust manifests without editing source files. Transformations modify resources programmatically before creation.
import * as k8s from "@pulumi/kubernetes";
const example = new k8s.yaml.ConfigGroup("example", {
files: "foo.yaml",
transformations: [
// Make every service private to the cluster, i.e., turn all services into ClusterIP instead of LoadBalancer.
(obj: any, opts: pulumi.CustomResourceOptions) => {
if (obj.kind === "Service" && obj.apiVersion === "v1") {
if (obj.spec && obj.spec.type && obj.spec.type === "LoadBalancer") {
obj.spec.type = "ClusterIP";
}
}
},
// Set a resource alias for a previous name.
(obj: any, opts: pulumi.CustomResourceOptions) => {
if (obj.kind === "Deployment") {
opts.aliases = [{ name: "oldName" }]
}
},
// Omit a resource from the Chart by transforming the specified resource definition to an empty List.
(obj: any, opts: pulumi.CustomResourceOptions) => {
if (obj.kind === "Pod" && obj.metadata.name === "test") {
obj.apiVersion = "v1"
obj.kind = "List"
}
},
],
});
from pulumi_kubernetes.yaml import ConfigGroup
# Make every service private to the cluster, i.e., turn all services into ClusterIP instead of LoadBalancer.
def make_service_private(obj, opts):
if obj["kind"] == "Service" and obj["apiVersion"] == "v1":
try:
t = obj["spec"]["type"]
if t == "LoadBalancer":
obj["spec"]["type"] = "ClusterIP"
except KeyError:
pass
# Set a resource alias for a previous name.
def alias(obj, opts):
if obj["kind"] == "Deployment":
opts.aliases = ["oldName"]
# Omit a resource from the Chart by transforming the specified resource definition to an empty List.
def omit_resource(obj, opts):
if obj["kind"] == "Pod" and obj["metadata"]["name"] == "test":
obj["apiVersion"] = "v1"
obj["kind"] = "List"
example = ConfigGroup(
"example",
files=["foo.yaml"],
transformations=[make_service_private, alias, omit_resource],
)
package main
import (
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/yaml"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := yaml.NewConfigGroup(ctx, "example",
&yaml.ConfigGroupArgs{
Files: []string{"foo.yaml"},
Transformations: []yaml.Transformation{
// Make every service private to the cluster, i.e., turn all services into ClusterIP
// instead of LoadBalancer.
func(state map[string]interface{}, opts ...pulumi.ResourceOption) {
if state["kind"] == "Service" {
spec := state["spec"].(map[string]interface{})
spec["type"] = "ClusterIP"
}
},
// Set a resource alias for a previous name.
func(state map[string]interface{}, opts ...pulumi.ResourceOption) {
if state["kind"] == "Deployment" {
aliases := pulumi.Aliases([]pulumi.Alias{
{
Name: pulumi.String("oldName"),
},
})
opts = append(opts, aliases)
}
},
// Omit a resource from the Chart by transforming the specified resource definition
// to an empty List.
func(state map[string]interface{}, opts ...pulumi.ResourceOption) {
name := state["metadata"].(map[string]interface{})["name"]
if state["kind"] == "Pod" && name == "test" {
state["apiVersion"] = "core/v1"
state["kind"] = "List"
}
},
},
},
)
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Pulumi;
using Pulumi.Kubernetes.Yaml;
class YamlStack : Stack
{
public YamlStack()
{
var helloWorld = new ConfigGroup("example", new ConfigGroupArgs
{
Files = new[] { "foo.yaml" },
Transformations =
{
LoadBalancerToClusterIP,
ResourceAlias,
OmitTestPod,
}
});
// Make every service private to the cluster, i.e., turn all services into ClusterIP instead of LoadBalancer.
ImmutableDictionary<string, object> LoadBalancerToClusterIP(ImmutableDictionary<string, object> obj, CustomResourceOptions opts)
{
if ((string)obj["kind"] == "Service" && (string)obj["apiVersion"] == "v1")
{
var spec = (ImmutableDictionary<string, object>)obj["spec"];
if (spec != null && (string)spec["type"] == "LoadBalancer")
{
return obj.SetItem("spec", spec.SetItem("type", "ClusterIP"));
}
}
return obj;
}
// Set a resource alias for a previous name.
ImmutableDictionary<string, object> ResourceAlias(ImmutableDictionary<string, object> obj, CustomResourceOptions opts)
{
if ((string)obj["kind"] == "Deployment")
{
opts.Aliases.Add(new Alias { Name = "oldName" });
}
return obj;
}
// Omit a resource from the Chart by transforming the specified resource definition to an empty List.
ImmutableDictionary<string, object> OmitTestPod(ImmutableDictionary<string, object> obj, CustomResourceOptions opts)
{
var metadata = (ImmutableDictionary<string, object>)obj["metadata"];
if ((string)obj["kind"] == "Pod" && (string)metadata["name"] == "test")
{
return new Dictionary<string, object>
{
["apiVersion"] = "v1",
["kind"] = "List",
["items"] = new Dictionary<string, object>(),
}.ToImmutableDictionary();
}
return obj;
}
}
}
Each transformation receives the resource object (obj) and resource options (opts). The function can modify properties, set aliases, or convert resources to empty Lists to skip them. Transformations run in order, allowing you to chain modifications. The example shows three common patterns: changing Service types, setting resource aliases, and filtering out specific resources.
Beyond these examples
These snippets focus on specific ConfigGroup features: file and pattern-based YAML loading, inline YAML string definitions, and runtime resource transformations. They’re intentionally minimal rather than full Kubernetes deployments.
The examples assume pre-existing infrastructure such as a Kubernetes cluster with configured access, and YAML manifest files for file-based examples. They focus on loading and transforming YAML rather than provisioning cluster infrastructure.
To keep things focused, common ConfigGroup patterns are omitted, including:
- Resource prefix customization (resourcePrefix)
- Pre-parsed object definitions (objs property)
- Namespace targeting and filtering
- Error handling for malformed YAML
These omissions are intentional: the goal is to illustrate how each ConfigGroup feature is wired, not provide drop-in deployment modules. See the ConfigGroup resource reference for all available configuration options.
Let's deploy Kubernetes Resources from YAML
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Version & Migration
kubernetes.yaml/v2.ConfigGroup with improvements. v1 remains available but consider migrating to v2.YAML Input Methods
You have four options:
- Single file -
files: "foo.yaml" - Multiple files -
files: ["foo.yaml", "bar.yaml"] - Glob patterns -
files: "yaml/*.yaml" - Inline YAML - Use the
yamlproperty with literal YAML strings
files: "yaml/*.yaml" for a single pattern, or files: ["foo/*.yaml", "bar/*.yaml"] for multiple patterns.Resource Transformations
transformations property with an array of functions. Each function receives the resource object and options, allowing you to modify properties before registration.Transformations support three common patterns:
- Modify properties - Change Service type from LoadBalancer to ClusterIP
- Set aliases - Add resource aliases for previous names
- Omit resources - Transform specific resources to empty Lists to exclude them
Resource Naming
resourcePrefix to add a prefix to auto-generated names. For example, resourcePrefix: "foo" produces resource names like “foo-resourceName”.