CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pulumi--kubernetes

A comprehensive Pulumi resource provider for creating and managing Kubernetes resources and workloads in a running cluster

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

yaml-deployment.mddocs/

YAML Deployment

The YAML deployment capabilities enable you to deploy Kubernetes resources from existing YAML manifests while gaining full Pulumi integration, resource management, and transformation capabilities.

Package Import

import { yaml } from "@pulumi/kubernetes";
import * as k8s from "@pulumi/kubernetes";

// Direct YAML imports
import { ConfigFile, ConfigGroup } from "@pulumi/kubernetes/yaml/v2";

CollectionComponentResource Base Class

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 (yaml/v2)

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
}

ConfigFile Usage Examples

// 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
});

Accessing Resources from ConfigFile

// 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 (yaml/v2)

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
}

ConfigGroup Usage Examples

// 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()}-`,
});

Advanced ConfigGroup Patterns

// 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");

Complete Application Examples

Microservices Application

// 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");

CI/CD Pipeline Integration

// 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 };
        },
    ],
});

Multi-Cluster Deployment

// 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");

Best Practices

YAML Management Best Practices

  1. File Organization: Organize YAML files by component, environment, or namespace
  2. Glob Patterns: Use glob patterns for flexible file selection
  3. Resource Naming: Use consistent naming conventions across manifests
  4. Namespace Management: Use namespace overrides rather than hardcoding namespaces
  5. Transformations: Use transformations for cross-cutting concerns

Deployment Best Practices

  1. Environment Separation: Use different directories or overlays for different environments
  2. Resource Dependencies: Use Pulumi dependencies to ensure proper deployment order
  3. Resource Access: Use the resource access methods for inter-resource references
  4. Error Handling: Implement proper error handling and rollback strategies
  5. Monitoring: Monitor deployed resources and implement health checks

Security Best Practices

  1. Secret Management: Use Pulumi secrets for sensitive data rather than plain YAML
  2. RBAC Integration: Apply appropriate RBAC configurations
  3. Network Policies: Include network policies in your manifests
  4. Resource Limits: Always specify resource requests and limits
  5. Image Security: Use specific image tags and trusted registries

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

docs

core-resources.md

helm-integration.md

index.md

kustomize-integration.md

networking-resources.md

provider-configuration.md

rbac-resources.md

storage-resources.md

workload-resources.md

yaml-deployment.md

tile.json