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

helm-integration.mddocs/

Helm Integration

The Helm integration provides powerful capabilities for deploying Helm charts as Pulumi resources without requiring Tiller. This enables declarative management of complex applications with transformation capabilities and full Pulumi lifecycle management.

Package Import

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

// Direct Helm imports
import { Chart } from "@pulumi/kubernetes/helm/v4";
import { Release } from "@pulumi/kubernetes/helm/v3";

Chart (helm/v4) - Recommended

Chart represents a Helm chart deployment as a Pulumi ComponentResource. This is the recommended approach for new deployments.

class Chart extends pulumi.ComponentResource {
    constructor(name: string, args: ChartArgs, opts?: pulumi.ComponentResourceOptions)
    
    // Method to get specific resources from the chart
    public getResource(groupVersionKind: string, name: string, namespace?: string): pulumi.CustomResource
    public getResourceProperty(groupVersionKind: string, name: string, property: string, namespace?: string): pulumi.Output<any>
}

interface ChartArgs {
    // Chart source options
    chart: pulumi.Input<string>;                     // Chart name or path (required)
    version?: pulumi.Input<string>;                  // Chart version
    repositoryOpts?: pulumi.Input<RepositoryOpts>;   // Repository configuration
    
    // Values and configuration
    values?: pulumi.Input<{[key: string]: any}>;     // Chart values
    valueYamlFiles?: pulumi.Input<pulumi.Input<pulumi.asset.Asset | pulumi.asset.Archive>[]>; // YAML value files
    
    // Deployment options
    name?: pulumi.Input<string>;                     // Release name
    namespace?: pulumi.Input<string>;                // Target namespace
    
    // Advanced options
    skipCrds?: pulumi.Input<boolean>;               // Skip CRD installation
    skipAwait?: pulumi.Input<boolean>;              // Skip waiting for resources to become ready
    dependencyUpdate?: pulumi.Input<boolean>;       // Update dependencies before deployment
    devel?: pulumi.Input<boolean>;                  // Use development versions
    
    // Security options
    verify?: pulumi.Input<boolean>;                 // Verify chart integrity
    keyring?: pulumi.Input<pulumi.asset.Asset | pulumi.asset.Archive>; // Public keys for verification
    
    // Resource management
    resourcePrefix?: pulumi.Input<string>;          // Prefix for auto-generated resource names
    postRenderer?: pulumi.Input<PostRenderer>;      // Post-renderer specification
}

interface RepositoryOpts {
    repo?: pulumi.Input<string>;                    // Repository URL
    username?: pulumi.Input<string>;                // Username for private repositories
    password?: pulumi.Input<string>;                // Password for private repositories
    caFile?: pulumi.Input<pulumi.asset.Asset | pulumi.asset.Archive>; // CA file asset
    certFile?: pulumi.Input<pulumi.asset.Asset | pulumi.asset.Archive>; // Certificate file asset
    keyFile?: pulumi.Input<pulumi.asset.Asset | pulumi.asset.Archive>; // Key file asset
}

Chart Usage Examples

// Deploy NGINX Ingress Controller from Bitnami repository
const nginxIngress = new k8s.helm.v4.Chart("nginx-ingress", {
    chart: "nginx-ingress-controller",
    version: "9.3.12",
    repositoryOpts: {
        repo: "https://charts.bitnami.com/bitnami",
    },
    namespace: "ingress-nginx",
    createNamespace: true,
    values: {
        replicaCount: 2,
        service: {
            type: "LoadBalancer",
            annotations: {
                "service.beta.kubernetes.io/aws-load-balancer-type": "nlb",
            },
        },
        metrics: {
            enabled: true,
            serviceMonitor: {
                enabled: true,
            },
        },
        resources: {
            requests: {
                cpu: "100m",
                memory: "128Mi",
            },
            limits: {
                cpu: "500m",
                memory: "512Mi",
            },
        },
    },
});

// Deploy PostgreSQL from local chart
const postgresql = new k8s.helm.v4.Chart("postgresql", {
    path: "./charts/postgresql",
    namespace: "database",
    createNamespace: true,
    values: {
        auth: {
            postgresPassword: "secure-password",
            database: "myapp",
        },
        persistence: {
            enabled: true,
            storageClass: "fast-ssd",
            size: "20Gi",
        },
        metrics: {
            enabled: true,
        },
    },
    dependencyUpdate: true,
});

// Deploy with multiple values files
const monitoring = new k8s.helm.v4.Chart("prometheus", {
    chart: "kube-prometheus-stack",
    version: "45.7.1", 
    repositoryOpts: {
        repo: "https://prometheus-community.github.io/helm-charts",
    },
    namespace: "monitoring",
    createNamespace: true,
    valuesFiles: [
        "./helm-values/prometheus-base.yaml",
        "./helm-values/prometheus-prod.yaml",
    ],
    values: {
        // Override specific values
        grafana: {
            adminPassword: "admin-secret",
            persistence: {
                enabled: true,
                size: "10Gi",
            },
        },
        prometheus: {
            prometheusSpec: {
                retention: "30d",
                storageSpec: {
                    volumeClaimTemplate: {
                        spec: {
                            storageClassName: "fast-ssd",
                            accessModes: ["ReadWriteOnce"],
                            resources: {
                                requests: {
                                    storage: "50Gi",
                                },
                            },
                        },
                    },
                },
            },
        },
    },
    timeout: 600, // 10 minutes
    atomic: true,
});

// Deploy with resource transformations
const app = new k8s.helm.v4.Chart("my-app", {
    chart: "my-app",
    repositoryOpts: {
        repo: "https://charts.example.com",
    },
    values: {
        image: {
            tag: "v1.2.3",
        },
    },
    transformations: [
        // Add common labels to all resources
        (args: any) => {
            if (args.type.startsWith("kubernetes:")) {
                args.props = pulumi.output(args.props).apply((props: any) => ({
                    ...props,
                    metadata: {
                        ...props.metadata,
                        labels: {
                            ...props.metadata?.labels,
                            "app.kubernetes.io/managed-by": "pulumi",
                            "environment": "production",
                        },
                    },
                }));
            }
            return {
                props: args.props,
                opts: args.opts,
            };
        },
        // Modify resource requirements
        (args: any) => {
            if (args.type === "kubernetes:apps/v1:Deployment") {
                args.props = pulumi.output(args.props).apply((props: any) => ({
                    ...props,
                    spec: {
                        ...props.spec,
                        template: {
                            ...props.spec.template,
                            spec: {
                                ...props.spec.template.spec,
                                containers: props.spec.template.spec.containers?.map((container: any) => ({
                                    ...container,
                                    resources: {
                                        requests: {
                                            cpu: "100m",
                                            memory: "128Mi",
                                        },
                                        limits: {
                                            cpu: "500m",
                                            memory: "512Mi",
                                        },
                                    },
                                })),
                            },
                        },
                    },
                }));
            }
            return {
                props: args.props,
                opts: args.opts,
            };
        },
    ],
});

// Private repository with authentication
const privateChart = new k8s.helm.v4.Chart("private-app", {
    chart: "private-app",
    version: "1.0.0",
    repositoryOpts: {
        repo: "https://private-charts.company.com",
        username: "chart-user",
        password: "chart-password",
    },
    namespace: "production",
    values: {
        image: {
            pullSecrets: ["private-registry-secret"],
        },
    },
});

Accessing Chart Resources

// Access specific resources from deployed chart
const nginxDeployment = nginxIngress.getResource("apps/v1/Deployment", "nginx-ingress-controller");
const nginxService = nginxIngress.getResource("v1/Service", "nginx-ingress-controller");

// Get specific properties from resources
const serviceIP = nginxIngress.getResourceProperty("v1/Service", "nginx-ingress-controller", "status");

// Export important values
export const ingressControllerIP = nginxService.status.loadBalancer.ingress[0].ip;
export const prometheusURL = monitoring.getResourceProperty("v1/Service", "prometheus-server", "spec").apply(spec => 
    `http://${spec.clusterIP}:${spec.ports[0].port}`
);

Release (helm/v3)

Release represents a Helm release using Helm v3 APIs. This provides compatibility with existing Helm workflows.

class Release extends pulumi.CustomResource {
    constructor(name: string, args: ReleaseArgs, opts?: pulumi.ResourceOptions)
    
    public static get(name: string, id: pulumi.Input<pulumi.ID>, opts?: pulumi.CustomResourceOptions): Release
    
    // Output properties
    public readonly status!: pulumi.Output<string>;
    public readonly version!: pulumi.Output<number>;
    public readonly namespace!: pulumi.Output<string>;
    public readonly values!: pulumi.Output<{[key: string]: any}>;
    public readonly chart!: pulumi.Output<string>;
    public readonly manifest!: pulumi.Output<string>;
}

interface ReleaseArgs {
    // Chart source
    chart?: pulumi.Input<string>;                    // Chart name or path
    version?: pulumi.Input<string>;                  // Chart version
    repositoryOpts?: pulumi.Input<RepositoryOpts>;   // Repository configuration
    
    // Release configuration
    name?: pulumi.Input<string>;                     // Release name (defaults to resource name)
    namespace?: pulumi.Input<string>;                // Target namespace
    createNamespace?: pulumi.Input<boolean>;         // Create namespace if needed
    
    // Values
    values?: pulumi.Input<{[key: string]: any}>;     // Release values
    valuesFiles?: pulumi.Input<string[]>;            // Values files
    
    // Deployment options
    timeout?: pulumi.Input<number>;                  // Timeout in seconds
    atomic?: pulumi.Input<boolean>;                  // Atomic deployment
    cleanupOnFail?: pulumi.Input<boolean>;           // Cleanup on failure
    dependencyUpdate?: pulumi.Input<boolean>;        // Update dependencies
    description?: pulumi.Input<string>;              // Release description
    devel?: pulumi.Input<boolean>;                   // Use development versions
    disableOpenapiValidation?: pulumi.Input<boolean>; // Skip OpenAPI validation
    disableWebhooks?: pulumi.Input<boolean>;         // Disable admission webhooks
    forceUpdate?: pulumi.Input<boolean>;             // Force update
    lint?: pulumi.Input<boolean>;                    // Lint chart before deployment
    maxHistory?: pulumi.Input<number>;               // Maximum revision history
    recreatePods?: pulumi.Input<boolean>;            // Recreate pods
    renderSubchartNotes?: pulumi.Input<boolean>;     // Render subchart notes
    replace?: pulumi.Input<boolean>;                 // Replace existing release
    resetValues?: pulumi.Input<boolean>;             // Reset values to defaults
    reuseValues?: pulumi.Input<boolean>;             // Reuse previous release values
    skipCrds?: pulumi.Input<boolean>;               // Skip CRDs
    skipTests?: pulumi.Input<boolean>;              // Skip tests
    verify?: pulumi.Input<boolean>;                 // Verify chart
    waitForJobs?: pulumi.Input<boolean>;            // Wait for jobs to complete
}

Release Usage Examples

// Basic release deployment
const nginxRelease = new k8s.helm.v3.Release("nginx", {
    chart: "nginx",
    repositoryOpts: {
        repo: "https://charts.bitnami.com/bitnami",
    },
    version: "13.2.12",
    namespace: "web",
    createNamespace: true,
    values: {
        replicaCount: 3,
        service: {
            type: "LoadBalancer",
        },
    },
});

// Release with comprehensive configuration
const redisRelease = new k8s.helm.v3.Release("redis-cluster", {
    chart: "redis",
    repositoryOpts: {
        repo: "https://charts.bitnami.com/bitnami",
    },
    version: "17.3.7",
    namespace: "cache",
    createNamespace: true,
    values: {
        architecture: "replication",
        auth: {
            enabled: true,
            password: "redis-password",
        },
        master: {
            persistence: {
                enabled: true,
                size: "8Gi",
                storageClass: "fast-ssd",
            },
        },
        replica: {
            replicaCount: 2,
            persistence: {
                enabled: true,
                size: "8Gi",
                storageClass: "fast-ssd",
            },
        },
        metrics: {
            enabled: true,
            serviceMonitor: {
                enabled: true,
            },
        },
    },
    timeout: 600,
    atomic: true,
    cleanupOnFail: true,
    dependencyUpdate: true,
    maxHistory: 5,
    waitForJobs: true,
});

// Release from local chart
const customAppRelease = new k8s.helm.v3.Release("custom-app", {
    chart: "./charts/custom-app",
    namespace: "applications",
    createNamespace: true,
    valuesFiles: [
        "./values/base.yaml",
        "./values/production.yaml",
    ],
    values: {
        image: {
            tag: "v2.1.0",
        },
        ingress: {
            enabled: true,
            hosts: ["app.example.com"],
            tls: [{
                secretName: "app-tls",
                hosts: ["app.example.com"],
            }],
        },
    },
    dependencyUpdate: true,
    lint: true,
});

Advanced Helm Patterns

Multi-Chart Application

// Database layer
const database = new k8s.helm.v4.Chart("database", {
    chart: "postgresql",
    repositoryOpts: {
        repo: "https://charts.bitnami.com/bitnami",
    },
    namespace: "data",
    createNamespace: true,
    values: {
        auth: {
            database: "appdb",
        },
        persistence: {
            size: "20Gi",
            storageClass: "database-ssd",
        },
    },
});

// Cache layer
const cache = new k8s.helm.v4.Chart("redis", {
    chart: "redis",
    repositoryOpts: {
        repo: "https://charts.bitnami.com/bitnami",
    },
    namespace: "cache",
    createNamespace: true,
    values: {
        architecture: "standalone",
        master: {
            persistence: {
                size: "5Gi",
            },
        },
    },
});

// Application layer (depends on database and cache)
const application = new k8s.helm.v4.Chart("app", {
    chart: "./charts/myapp",
    namespace: "application", 
    createNamespace: true,
    values: {
        database: {
            host: database.getResourceProperty("v1/Service", "postgresql", "metadata").name,
            port: 5432,
        },
        redis: {
            host: cache.getResourceProperty("v1/Service", "redis-master", "metadata").name,
            port: 6379,
        },
    },
}, {
    dependsOn: [database, cache],
});

Chart with Custom Resources

// Deploy operator first
const operator = new k8s.helm.v4.Chart("my-operator", {
    chart: "my-operator",
    repositoryOpts: {
        repo: "https://charts.example.com",
    },
    namespace: "operators",
    createNamespace: true,
    values: {
        image: {
            tag: "v1.0.0",
        },
        resources: {
            limits: {
                cpu: "200m",
                memory: "256Mi",
            },
        },
    },
    timeout: 300,
});

// Deploy application using custom resources
const customResourceApp = new k8s.helm.v4.Chart("custom-app", {
    chart: "custom-app",
    repositoryOpts: {
        repo: "https://charts.example.com", 
    },
    namespace: "applications",
    createNamespace: true,
    values: {
        customResource: {
            enabled: true,
            spec: {
                replicas: 3,
                version: "v2.0.0",
            },
        },
    },
}, {
    dependsOn: [operator],
});

Environment-Specific Configurations

// Base configuration
const baseValues = {
    replicaCount: 1,
    image: {
        repository: "myapp",
        tag: "latest",
        pullPolicy: "Always",
    },
    service: {
        type: "ClusterIP",
        port: 80,
    },
    resources: {
        requests: {
            cpu: "100m",
            memory: "128Mi",
        },
    },
};

// Development environment
const devValues = {
    ...baseValues,
    replicaCount: 1,
    image: {
        ...baseValues.image,
        tag: "dev",
    },
    ingress: {
        enabled: true,
        hosts: ["dev-app.example.com"],
    },
};

// Production environment
const prodValues = {
    ...baseValues,
    replicaCount: 3,
    image: {
        ...baseValues.image,
        tag: "v1.0.0",
        pullPolicy: "IfNotPresent",
    },
    service: {
        ...baseValues.service,
        type: "LoadBalancer",
    },
    resources: {
        requests: {
            cpu: "200m",
            memory: "256Mi",
        },
        limits: {
            cpu: "500m", 
            memory: "512Mi",
        },
    },
    ingress: {
        enabled: true,
        hosts: ["app.example.com"],
        tls: [{
            secretName: "app-tls",
            hosts: ["app.example.com"],
        }],
    },
    autoscaling: {
        enabled: true,
        minReplicas: 3,
        maxReplicas: 10,
        targetCPUUtilizationPercentage: 70,
    },
};

// Deploy based on environment
const environment = pulumi.getStack();
const values = environment === "production" ? prodValues : devValues;

const app = new k8s.helm.v4.Chart("myapp", {
    chart: "myapp",
    repositoryOpts: {
        repo: "https://charts.example.com",
    },
    namespace: `myapp-${environment}`,
    createNamespace: true,
    values: values,
});

Best Practices

Chart Management Best Practices

  1. Use Chart v4: Prefer helm.v4.Chart over helm.v3.Release for new deployments
  2. Version Pinning: Always specify chart versions for production deployments
  3. Values Organization: Use separate values files for different environments
  4. Resource Limits: Always set resource requests and limits
  5. Transformations: Use transformations for cross-cutting concerns like labels and annotations

Security Best Practices

  1. Private Repositories: Use credentials for private chart repositories
  2. Values Encryption: Encrypt sensitive values using Pulumi secrets
  3. RBAC: Ensure proper service account and RBAC configurations
  4. Image Security: Use specific image tags and trusted registries
  5. Network Policies: Apply network policies to restrict traffic

Operations Best Practices

  1. Atomic Deployments: Use atomic deployments for production
  2. Timeouts: Set appropriate timeouts for chart deployments
  3. Dependencies: Properly manage chart dependencies and update them
  4. Monitoring: Monitor chart deployments and resource health
  5. Rollback Strategy: Plan for rollback scenarios and test rollback procedures

The Helm integration provides powerful capabilities for managing complex Kubernetes applications while maintaining the benefits of Pulumi's infrastructure-as-code approach, enabling reliable and repeatable deployments across environments.

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