The kubernetes:apps/v1:Deployment resource, part of the Pulumi Kubernetes provider, manages Deployments that control ReplicaSets and Pods. This guide focuses on three capabilities: replica management with label-based selection, pod template configuration, and resource naming strategies.
Deployments require a configured Kubernetes cluster and reference container images that must be accessible. The examples are intentionally small. Combine them with your own resource limits, health checks, and update strategies.
Deploy replicated pods with label-based selection
Most workloads start with a Deployment that manages multiple pod replicas, ensuring the desired count stays running and handling rolling updates automatically.
import * as pulumi from "@pulumi/pulumi";
import * as kubernetes from "@pulumi/kubernetes";
const deployment = new kubernetes.apps.v1.Deployment("deployment", {
metadata: {
labels: {
app: "nginx",
},
},
spec: {
replicas: 3,
selector: {
matchLabels: {
app: "nginx",
},
},
template: {
metadata: {
labels: {
app: "nginx",
},
},
spec: {
containers: [{
image: "nginx:1.14.2",
name: "nginx",
ports: [{
containerPort: 80,
}],
}],
},
},
},
});
import pulumi
import pulumi_kubernetes as kubernetes
deployment = kubernetes.apps.v1.Deployment("deployment",
metadata=kubernetes.meta.v1.ObjectMetaArgs(
labels={
"app": "nginx",
},
),
spec=kubernetes.apps.v1.DeploymentSpecArgs(
replicas=3,
selector=kubernetes.meta.v1.LabelSelectorArgs(
match_labels={
"app": "nginx",
},
),
template=kubernetes.core.v1.PodTemplateSpecArgs(
metadata=kubernetes.meta.v1.ObjectMetaArgs(
labels={
"app": "nginx",
},
),
spec=kubernetes.core.v1.PodSpecArgs(
containers=[kubernetes.core.v1.ContainerArgs(
image="nginx:1.14.2",
name="nginx",
ports=[kubernetes.core.v1.ContainerPortArgs(
container_port=80,
)],
)],
),
),
))
package main
import (
appsv1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apps/v1"
corev1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/core/v1"
metav1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/meta/v1"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := appsv1.NewDeployment(ctx, "deployment", &appsv1.DeploymentArgs{
Metadata: &metav1.ObjectMetaArgs{
Labels: pulumi.StringMap{
"app": pulumi.String("nginx"),
},
},
Spec: &appsv1.DeploymentSpecArgs{
Replicas: pulumi.Int(3),
Selector: &metav1.LabelSelectorArgs{
MatchLabels: pulumi.StringMap{
"app": pulumi.String("nginx"),
},
},
Template: &corev1.PodTemplateSpecArgs{
Metadata: &metav1.ObjectMetaArgs{
Labels: pulumi.StringMap{
"app": pulumi.String("nginx"),
},
},
Spec: &corev1.PodSpecArgs{
Containers: corev1.ContainerArray{
&corev1.ContainerArgs{
Image: pulumi.String("nginx:1.14.2"),
Name: pulumi.String("nginx"),
Ports: corev1.ContainerPortArray{
&corev1.ContainerPortArgs{
ContainerPort: pulumi.Int(80),
},
},
},
},
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Kubernetes = Pulumi.Kubernetes;
return await Deployment.RunAsync(() =>
{
var deployment = new Kubernetes.Apps.V1.Deployment("deployment", new()
{
Metadata = new Kubernetes.Types.Inputs.Meta.V1.ObjectMetaArgs
{
Labels =
{
{ "app", "nginx" },
},
},
Spec = new Kubernetes.Types.Inputs.Apps.V1.DeploymentSpecArgs
{
Replicas = 3,
Selector = new Kubernetes.Types.Inputs.Meta.V1.LabelSelectorArgs
{
MatchLabels =
{
{ "app", "nginx" },
},
},
Template = new Kubernetes.Types.Inputs.Core.V1.PodTemplateSpecArgs
{
Metadata = new Kubernetes.Types.Inputs.Meta.V1.ObjectMetaArgs
{
Labels =
{
{ "app", "nginx" },
},
},
Spec = new Kubernetes.Types.Inputs.Core.V1.PodSpecArgs
{
Containers = new[]
{
new Kubernetes.Types.Inputs.Core.V1.ContainerArgs
{
Image = "nginx:1.14.2",
Name = "nginx",
Ports = new[]
{
new Kubernetes.Types.Inputs.Core.V1.ContainerPortArgs
{
ContainerPortValue = 80,
},
},
},
},
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.kubernetes.apps_v1.Deployment;
import com.pulumi.kubernetes.apps_v1.DeploymentArgs;
import com.pulumi.kubernetes.meta_v1.inputs.ObjectMetaArgs;
import com.pulumi.kubernetes.apps_v1.inputs.DeploymentSpecArgs;
import com.pulumi.kubernetes.meta_v1.inputs.LabelSelectorArgs;
import com.pulumi.kubernetes.core_v1.inputs.PodTemplateSpecArgs;
import com.pulumi.kubernetes.core_v1.inputs.PodSpecArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var deployment = new Deployment("deployment", DeploymentArgs.builder()
.metadata(ObjectMetaArgs.builder()
.labels(Map.of("app", "nginx"))
.build())
.spec(DeploymentSpecArgs.builder()
.replicas(3)
.selector(LabelSelectorArgs.builder()
.matchLabels(Map.of("app", "nginx"))
.build())
.template(PodTemplateSpecArgs.builder()
.metadata(ObjectMetaArgs.builder()
.labels(Map.of("app", "nginx"))
.build())
.spec(PodSpecArgs.builder()
.containers(ContainerArgs.builder()
.image("nginx:1.14.2")
.name("nginx")
.ports(ContainerPortArgs.builder()
.containerPort(80)
.build())
.build())
.build())
.build())
.build())
.build());
}
}
description: Create a Deployment with auto-naming
name: yaml-example
resources:
deployment:
properties:
metadata:
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2
name: nginx
ports:
- containerPort: 80
type: kubernetes:apps/v1:Deployment
runtime: yaml
The Deployment creates and maintains three nginx pods. The selector.matchLabels property tells the Deployment which pods it manages (those with app: nginx). The template defines the pod specification: container image, ports, and labels. Kubernetes continuously reconciles the actual pod count with the replicas value, replacing failed pods automatically.
Create a deployment with an explicit name
When you need predictable resource names for scripting or cross-stack references, specify the Deployment name explicitly rather than letting Pulumi generate one.
import * as pulumi from "@pulumi/pulumi";
import * as kubernetes from "@pulumi/kubernetes";
const deployment = new kubernetes.apps.v1.Deployment("deployment", {
metadata: {
labels: {
app: "nginx",
},
name: "nginx-deployment",
},
spec: {
replicas: 3,
selector: {
matchLabels: {
app: "nginx",
},
},
template: {
metadata: {
labels: {
app: "nginx",
},
},
spec: {
containers: [{
image: "nginx:1.14.2",
name: "nginx",
ports: [{
containerPort: 80,
}],
}],
},
},
},
});
import pulumi
import pulumi_kubernetes as kubernetes
deployment = kubernetes.apps.v1.Deployment("deployment",
metadata=kubernetes.meta.v1.ObjectMetaArgs(
labels={
"app": "nginx",
},
name="nginx-deployment",
),
spec=kubernetes.apps.v1.DeploymentSpecArgs(
replicas=3,
selector=kubernetes.meta.v1.LabelSelectorArgs(
match_labels={
"app": "nginx",
},
),
template=kubernetes.core.v1.PodTemplateSpecArgs(
metadata=kubernetes.meta.v1.ObjectMetaArgs(
labels={
"app": "nginx",
},
),
spec=kubernetes.core.v1.PodSpecArgs(
containers=[kubernetes.core.v1.ContainerArgs(
image="nginx:1.14.2",
name="nginx",
ports=[kubernetes.core.v1.ContainerPortArgs(
container_port=80,
)],
)],
),
),
))
package main
import (
appsv1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apps/v1"
corev1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/core/v1"
metav1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/meta/v1"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := appsv1.NewDeployment(ctx, "deployment", &appsv1.DeploymentArgs{
Metadata: &metav1.ObjectMetaArgs{
Labels: pulumi.StringMap{
"app": pulumi.String("nginx"),
},
Name: pulumi.String("nginx-deployment"),
},
Spec: &appsv1.DeploymentSpecArgs{
Replicas: pulumi.Int(3),
Selector: &metav1.LabelSelectorArgs{
MatchLabels: pulumi.StringMap{
"app": pulumi.String("nginx"),
},
},
Template: &corev1.PodTemplateSpecArgs{
Metadata: &metav1.ObjectMetaArgs{
Labels: pulumi.StringMap{
"app": pulumi.String("nginx"),
},
},
Spec: &corev1.PodSpecArgs{
Containers: corev1.ContainerArray{
&corev1.ContainerArgs{
Image: pulumi.String("nginx:1.14.2"),
Name: pulumi.String("nginx"),
Ports: corev1.ContainerPortArray{
&corev1.ContainerPortArgs{
ContainerPort: pulumi.Int(80),
},
},
},
},
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Kubernetes = Pulumi.Kubernetes;
return await Deployment.RunAsync(() =>
{
var deployment = new Kubernetes.Apps.V1.Deployment("deployment", new()
{
Metadata = new Kubernetes.Types.Inputs.Meta.V1.ObjectMetaArgs
{
Labels =
{
{ "app", "nginx" },
},
Name = "nginx-deployment",
},
Spec = new Kubernetes.Types.Inputs.Apps.V1.DeploymentSpecArgs
{
Replicas = 3,
Selector = new Kubernetes.Types.Inputs.Meta.V1.LabelSelectorArgs
{
MatchLabels =
{
{ "app", "nginx" },
},
},
Template = new Kubernetes.Types.Inputs.Core.V1.PodTemplateSpecArgs
{
Metadata = new Kubernetes.Types.Inputs.Meta.V1.ObjectMetaArgs
{
Labels =
{
{ "app", "nginx" },
},
},
Spec = new Kubernetes.Types.Inputs.Core.V1.PodSpecArgs
{
Containers = new[]
{
new Kubernetes.Types.Inputs.Core.V1.ContainerArgs
{
Image = "nginx:1.14.2",
Name = "nginx",
Ports = new[]
{
new Kubernetes.Types.Inputs.Core.V1.ContainerPortArgs
{
ContainerPortValue = 80,
},
},
},
},
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.kubernetes.apps_v1.Deployment;
import com.pulumi.kubernetes.apps_v1.DeploymentArgs;
import com.pulumi.kubernetes.meta_v1.inputs.ObjectMetaArgs;
import com.pulumi.kubernetes.apps_v1.inputs.DeploymentSpecArgs;
import com.pulumi.kubernetes.meta_v1.inputs.LabelSelectorArgs;
import com.pulumi.kubernetes.core_v1.inputs.PodTemplateSpecArgs;
import com.pulumi.kubernetes.core_v1.inputs.PodSpecArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var deployment = new Deployment("deployment", DeploymentArgs.builder()
.metadata(ObjectMetaArgs.builder()
.labels(Map.of("app", "nginx"))
.name("nginx-deployment")
.build())
.spec(DeploymentSpecArgs.builder()
.replicas(3)
.selector(LabelSelectorArgs.builder()
.matchLabels(Map.of("app", "nginx"))
.build())
.template(PodTemplateSpecArgs.builder()
.metadata(ObjectMetaArgs.builder()
.labels(Map.of("app", "nginx"))
.build())
.spec(PodSpecArgs.builder()
.containers(ContainerArgs.builder()
.image("nginx:1.14.2")
.name("nginx")
.ports(ContainerPortArgs.builder()
.containerPort(80)
.build())
.build())
.build())
.build())
.build())
.build());
}
}
description: Create a Deployment with a user-specified name
name: yaml-example
resources:
deployment:
properties:
metadata:
labels:
app: nginx
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2
name: nginx
ports:
- containerPort: 80
type: kubernetes:apps/v1:Deployment
runtime: yaml
Setting metadata.name to “nginx-deployment” creates a Deployment with that exact name in Kubernetes. Without this property, Pulumi generates a unique name based on the resource logical name and a random suffix. Explicit names make it easier to reference the Deployment from kubectl commands or other infrastructure code.
Beyond these examples
These snippets focus on specific Deployment-level features: replica management and pod templates, label-based pod selection, and explicit vs auto-generated naming. They’re intentionally minimal rather than full application deployments.
The examples assume pre-existing infrastructure such as a Kubernetes cluster with configured access and container images in accessible registries. They focus on configuring the Deployment rather than provisioning the surrounding infrastructure.
To keep things focused, common Deployment patterns are omitted, including:
- Resource limits and requests (resources)
- Health checks (livenessProbe, readinessProbe)
- Update strategies (strategy.type, rollingUpdate)
- Namespace placement and annotations
These omissions are intentional: the goal is to illustrate how each Deployment feature is wired, not provide drop-in application modules. See the Deployment resource reference for all available configuration options.
Let's create a Kubernetes Deployment
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Deployment Readiness & Timeouts
customTimeouts option on the resource.status.conditions shows Available as True, and (4) for updates (generation > 1), status.conditions shows Progressing as True with reason NewReplicaSetAvailable.Progressing status. Updates (generation > 1) perform rollouts and require the Progressing condition to be True.Configuration & Labels
spec.selector.matchLabels must exactly match spec.template.metadata.labels for the Deployment to correctly manage its pods. All examples show this matching pattern (e.g., both set to app: nginx).metadata.name and Pulumi will auto-generate a unique name. Alternatively, specify metadata.name explicitly (e.g., nginx-deployment) for a fixed name.