A comprehensive Pulumi resource provider for creating and managing Kubernetes resources and workloads in a running cluster
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The YAML deployment capabilities enable you to deploy Kubernetes resources from existing YAML manifests while gaining full Pulumi integration, resource management, and transformation capabilities.
import { yaml } from "@pulumi/kubernetes";
import * as k8s from "@pulumi/kubernetes";
// Direct YAML imports
import { ConfigFile, ConfigGroup } from "@pulumi/kubernetes/yaml/v2";Base class that provides strongly-typed resource lookup for YAML-based collections.
abstract class CollectionComponentResource extends pulumi.ComponentResource {
// Strongly-typed resource lookup method
public getResource<T extends pulumi.CustomResource>(
group: string,
version: string,
kind: string,
name: string,
namespace?: string
): T
// Get resource by GroupVersionKind string
public getResource(groupVersionKind: string, name: string, namespace?: string): pulumi.CustomResource
// Get specific property from resource
public getResourceProperty(groupVersionKind: string, name: string, property: string, namespace?: string): pulumi.Output<any>
}ConfigFile deploys resources from a single YAML manifest file with full Pulumi lifecycle management.
class ConfigFile extends CollectionComponentResource {
constructor(name: string, args: ConfigFileArgs, opts?: pulumi.ComponentResourceOptions)
// Resource access methods inherited from CollectionComponentResource
}
interface ConfigFileArgs {
// File specification
file: pulumi.Input<string>; // Path to YAML file (required)
// Resource configuration
resourcePrefix?: pulumi.Input<string>; // Prefix for resource names
// Deployment options
skipAwait?: pulumi.Input<boolean>; // Skip waiting for resource readiness
}// Deploy from single YAML file
const nginxManifest = new k8s.yaml.v2.ConfigFile("nginx-manifest", {
file: "./manifests/nginx-deployment.yaml",
});
// Deploy from multiple YAML files
const appManifests = new k8s.yaml.v2.ConfigFile("app-manifests", {
files: [
"./manifests/deployment.yaml",
"./manifests/service.yaml",
"./manifests/ingress.yaml",
],
});
// Deploy with namespace override
const devApp = new k8s.yaml.v2.ConfigFile("dev-app", {
file: "./manifests/app.yaml",
namespace: "development", // Override namespace in YAML
});
// Deploy with resource name prefix
const prefixedApp = new k8s.yaml.v2.ConfigFile("prefixed-app", {
file: "./manifests/app.yaml",
resourcePrefix: "staging-", // Prefix all resource names
});
// Deploy with await disabled for faster deployment
const fastApp = new k8s.yaml.v2.ConfigFile("fast-app", {
file: "./manifests/app.yaml",
skipAwait: true, // Don't wait for resources to become ready
});// Get specific resources from the deployed manifest
const deployment = appManifests.getResource("apps/v1", "Deployment", "nginx-deployment");
const service = appManifests.getResource("v1", "Service", "nginx-service");
// Using generic method with type assertion
const ingress = appManifests.getResource("networking.k8s.io/v1/Ingress", "nginx-ingress");
// Get resource properties
const serviceIP = appManifests.getResourceProperty("v1/Service", "nginx-service", "status");
const deploymentReplicas = appManifests.getResourceProperty("apps/v1/Deployment", "nginx-deployment", "spec.replicas");
// Export important values
export const loadBalancerIP = service.status.loadBalancer.ingress[0].ip;
export const ingressHostname = ingress.status.loadBalancer.ingress[0].hostname;ConfigGroup deploys resources from multiple YAML files or directories with pattern matching capabilities.
class ConfigGroup extends CollectionComponentResource {
constructor(name: string, args: ConfigGroupArgs, opts?: pulumi.ComponentResourceOptions)
// Resource access methods inherited from CollectionComponentResource
}
interface ConfigGroupArgs {
// File specification
files?: pulumi.Input<pulumi.Input<string>[]>; // Array of file paths (supports glob patterns)
// Content specification
yaml?: pulumi.Input<string>; // YAML content string
objs?: pulumi.Input<any[]>; // Array of Kubernetes objects
// Resource configuration
resourcePrefix?: pulumi.Input<string>; // Prefix for resource names
// Deployment options
skipAwait?: pulumi.Input<boolean>; // Skip waiting for resource readiness
}// Deploy all YAML files from directory using glob pattern
const allManifests = new k8s.yaml.v2.ConfigGroup("all-manifests", {
files: ["./manifests/**/*.yaml"],
namespace: "applications",
});
// Deploy specific files
const coreServices = new k8s.yaml.v2.ConfigGroup("core-services", {
files: [
"./manifests/database/*.yaml",
"./manifests/cache/redis.yaml",
"./manifests/monitoring/prometheus.yaml",
],
namespace: "infrastructure",
});
// Deploy from YAML content strings
const inlineManifests = new k8s.yaml.v2.ConfigGroup("inline-manifests", {
yaml: [
`
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database.url: "postgresql://db:5432/app"
redis.host: "redis:6379"
`,
`
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: app
image: myapp:v1.0
ports:
- containerPort: 8080
`,
],
});
// Deploy from Kubernetes objects
const objectManifests = new k8s.yaml.v2.ConfigGroup("object-manifests", {
objs: [
{
apiVersion: "v1",
kind: "Namespace",
metadata: {
name: "my-application",
labels: {
environment: "production",
},
},
},
{
apiVersion: "v1",
kind: "Secret",
metadata: {
name: "app-secrets",
namespace: "my-application",
},
type: "Opaque",
stringData: {
username: "admin",
password: "secret-password",
},
},
],
});
// Environment-specific deployment
const envManifests = new k8s.yaml.v2.ConfigGroup("env-manifests", {
files: [
"./manifests/base/*.yaml",
`./manifests/overlays/${pulumi.getStack()}/*.yaml`,
],
namespace: `app-${pulumi.getStack()}`,
resourcePrefix: `${pulumi.getStack()}-`,
});// Multi-environment deployment with transformations
const createEnvironmentDeployment = (environment: string) => {
return new k8s.yaml.v2.ConfigGroup(`app-${environment}`, {
files: [
"./manifests/base/*.yaml",
`./manifests/overlays/${environment}/*.yaml`,
],
namespace: `app-${environment}`,
transformations: [
// Environment-specific labels
(args: any) => {
if (args.type.startsWith("kubernetes:")) {
args.props = pulumi.output(args.props).apply((props: any) => ({
...props,
metadata: {
...props.metadata,
labels: {
...props.metadata?.labels,
environment: environment,
"deployment.kubernetes.io/revision": "1",
},
},
}));
}
return { props: args.props, opts: args.opts };
},
// Environment-specific resource scaling
(args: any) => {
if (args.type === "kubernetes:apps/v1:Deployment") {
const replicas = environment === "production" ? 3 : 1;
args.props = pulumi.output(args.props).apply((props: any) => ({
...props,
spec: {
...props.spec,
replicas: replicas,
},
}));
}
return { props: args.props, opts: args.opts };
},
],
});
};
// Deploy to multiple environments
const devDeployment = createEnvironmentDeployment("development");
const stagingDeployment = createEnvironmentDeployment("staging");
const prodDeployment = createEnvironmentDeployment("production");// Deploy database layer
const databaseLayer = new k8s.yaml.v2.ConfigGroup("database", {
files: ["./manifests/database/*.yaml"],
namespace: "data",
transformations: [
(args: any) => {
// Add persistence annotations
if (args.type === "kubernetes:apps/v1:StatefulSet") {
args.props = pulumi.output(args.props).apply((props: any) => ({
...props,
metadata: {
...props.metadata,
annotations: {
...props.metadata?.annotations,
"backup.kubernetes.io/enabled": "true",
},
},
}));
}
return { props: args.props, opts: args.opts };
},
],
});
// Deploy application services
const appServices = new k8s.yaml.v2.ConfigGroup("app-services", {
files: [
"./manifests/services/user-service/*.yaml",
"./manifests/services/order-service/*.yaml",
"./manifests/services/payment-service/*.yaml",
],
namespace: "applications",
transformations: [
(args: any) => {
// Add service mesh annotations
if (args.type === "kubernetes:apps/v1:Deployment") {
args.props = pulumi.output(args.props).apply((props: any) => ({
...props,
spec: {
...props.spec,
template: {
...props.spec.template,
metadata: {
...props.spec.template.metadata,
annotations: {
...props.spec.template.metadata?.annotations,
"sidecar.istio.io/inject": "true",
"prometheus.io/scrape": "true",
"prometheus.io/port": "9090",
},
},
},
},
}));
}
return { props: args.props, opts: args.opts };
},
],
}, {
dependsOn: [databaseLayer],
});
// Deploy gateway and ingress
const gateway = new k8s.yaml.v2.ConfigFile("api-gateway", {
files: [
"./manifests/gateway/gateway.yaml",
"./manifests/gateway/virtualservice.yaml",
],
namespace: "istio-system",
}, {
dependsOn: [appServices],
});
// Access deployed resources
const userService = appServices.getResource("v1", "Service", "user-service", "applications");
const orderDeployment = appServices.getResource("apps/v1", "Deployment", "order-service", "applications");
// Export service endpoints
export const userServiceEndpoint = userService.spec.clusterIP;
export const gatewayURL = gateway.getResourceProperty("networking.istio.io/v1beta1/Gateway", "api-gateway", "status");// Deploy from CI/CD generated manifests
const cicdDeployment = new k8s.yaml.v2.ConfigGroup("cicd-deployment", {
files: [`./build/manifests/${pulumi.getStack()}/*.yaml`],
namespace: `app-${pulumi.getStack()}`,
transformations: [
// Add CI/CD metadata
(args: any) => {
if (args.type.startsWith("kubernetes:")) {
args.props = pulumi.output(args.props).apply((props: any) => ({
...props,
metadata: {
...props.metadata,
annotations: {
...props.metadata?.annotations,
"deployment.kubernetes.io/revision": process.env.BUILD_NUMBER || "unknown",
"git.commit": process.env.GIT_COMMIT || "unknown",
"ci.pipeline": process.env.CI_PIPELINE_ID || "unknown",
},
labels: {
...props.metadata?.labels,
"app.kubernetes.io/version": process.env.APP_VERSION || "latest",
},
},
}));
}
return { props: args.props, opts: args.opts };
},
// Environment-specific resource adjustments
(args: any) => {
const stack = pulumi.getStack();
if (args.type === "kubernetes:apps/v1:Deployment") {
args.props = pulumi.output(args.props).apply((props: any) => ({
...props,
spec: {
...props.spec,
replicas: stack === "production" ? 5 : 2,
template: {
...props.spec.template,
spec: {
...props.spec.template.spec,
containers: props.spec.template.spec.containers?.map((container: any) => ({
...container,
resources: {
requests: {
cpu: stack === "production" ? "200m" : "100m",
memory: stack === "production" ? "256Mi" : "128Mi",
},
limits: {
cpu: stack === "production" ? "1" : "500m",
memory: stack === "production" ? "1Gi" : "512Mi",
},
},
})),
},
},
},
}));
}
return { props: args.props, opts: args.opts };
},
],
});// Deploy to multiple clusters with different configurations
const deployToCluster = (clusterName: string, region: string) => {
return new k8s.yaml.v2.ConfigGroup(`app-${clusterName}`, {
files: ["./manifests/app/*.yaml"],
namespace: "applications",
transformations: [
// Cluster-specific labels and annotations
(args: any) => {
if (args.type.startsWith("kubernetes:")) {
args.props = pulumi.output(args.props).apply((props: any) => ({
...props,
metadata: {
...props.metadata,
labels: {
...props.metadata?.labels,
"cluster": clusterName,
"region": region,
},
annotations: {
...props.metadata?.annotations,
"deployment.cluster": clusterName,
},
},
}));
}
return { props: args.props, opts: args.opts };
},
// Regional configuration
(args: any) => {
if (args.type === "v1/Service" && args.props.spec?.type === "LoadBalancer") {
args.props = pulumi.output(args.props).apply((props: any) => ({
...props,
metadata: {
...props.metadata,
annotations: {
...props.metadata?.annotations,
"service.beta.kubernetes.io/aws-load-balancer-type":
region.startsWith("us-") ? "nlb" : "classic",
},
},
}));
}
return { props: args.props, opts: args.opts };
},
],
});
};
// Deploy to multiple clusters
const usEast1Deployment = deployToCluster("us-east-1", "us-east-1");
const usWest2Deployment = deployToCluster("us-west-2", "us-west-2");
const euWest1Deployment = deployToCluster("eu-west-1", "eu-west-1");The YAML deployment capabilities provide a bridge between traditional Kubernetes manifests and modern infrastructure-as-code practices, enabling gradual migration while gaining the benefits of Pulumi's resource management and transformation capabilities.
Install with Tessl CLI
npx tessl i tessl/npm-pulumi--kubernetes