Skip to main content
Pulumi logo Pulumi logo
  1. Docs
  2. Infrastructure as Code
  3. Guides
  4. Clouds
  5. AWS
  6. EKS

AWS Elastic Kubernetes Service (EKS)

    Amazon Elastic Kubernetes Service (Amazon EKS) is a managed Kubernetes service for deploying, managing, and scaling containerized applications on AWS. Amazon EKS runs the Kubernetes management infrastructure for you across multiple AWS availability zones to eliminate a single point of failure. Amazon EKS is certified Kubernetes conformant, so you can use existing tooling and plugins from partners and the Kubernetes community. Applications running on any standard Kubernetes environment are fully compatible with Amazon EKS and can be migrated to it.

    Overview

    Pulumi’s EKS component simplifies the creation, configuration, and management of EKS clusters. When used in combination with the Pulumi Kubernetes Provider, AWS Provider, and AWSx component package, you can use a single tool to manage your Kubernetes application configuration as well as your cluster and associated infrastructure.

    If you’re new to deploying applications onto Kubernetes with Pulumi, the Kubernetes get started tutorial is a good place to start before provisioning an EKS cluster of your own.

    Amazon EKS runs up-to-date versions of the open-source Kubernetes software, so you can use all the existing plugins and tooling from the Kubernetes community, including Pulumi’s support for deploying Helm charts. Applications running on Amazon EKS are fully compatible with applications running on any standard Kubernetes environment, whether running in on-premises data centers or public clouds, easing porting from other Kubernetes environments to EKS.

    Expressing your infrastructure and Kubernetes configuration in code using Pulumi ensures your resulting system is ready for production using built-in best practices.

    Prerequisites

    Before getting started, install these prerequisites:

    These are not required but are recommended if you plan on interacting with your Kubernetes cluster:

    • kubectl: the standard Kubernetes command line interface.
    • helm: if you plan on deploying Helm charts to your cluster.

    Provisioning a new EKS cluster

    To create a new EKS cluster, create an instance of the eks.Cluster class in your Pulumi program:

    import * as pulumi from "@pulumi/pulumi";
    import * as eks from "@pulumi/eks";
    
    // Create an EKS cluster with the default configuration.
    const cluster = new eks.Cluster("cluster", {});
    
    // Export the cluster's kubeconfig.
    export const kubeconfig = cluster.kubeconfig;
    
    import pulumi
    import pulumi_eks as eks
    
    # Create an EKS cluster with the default configuration.
    cluster = eks.Cluster("cluster")
    
    # Export the cluster's kubeconfig.
    pulumi.export("kubeconfig", cluster.kubeconfig)
    
    package main
    
    import (
    	"github.com/pulumi/pulumi-eks/sdk/v4/go/eks"
    	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    )
    
    func main() {
    	pulumi.Run(func(ctx *pulumi.Context) error {
    		// Create an EKS cluster with the default configuration.
    		cluster, err := eks.NewCluster(ctx, "cluster", nil)
    		if err != nil {
    			return err
    		}
    		// Export the cluster's kubeconfig.
    		ctx.Export("kubeconfig", cluster.Kubeconfig)
    		return nil
    	})
    }
    
    using System.Collections.Generic;
    using Pulumi;
    using Eks = Pulumi.Eks;
    
    return await Deployment.RunAsync(() =>
    {
        // Create an EKS cluster with the default configuration.
        var cluster = new Eks.Cluster("cluster");
    
        return new Dictionary<string, object?>
        {
            // Export the cluster's kubeconfig.
            ["kubeconfig"] = cluster.Kubeconfig,
        };
    });
    
    package myproject;
    
    import com.pulumi.Context;
    import com.pulumi.Pulumi;
    import com.pulumi.core.Output;
    import com.pulumi.eks.Cluster;
    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) {
            // Create an EKS cluster with the default configuration.
            var cluster = new Cluster("cluster");
    
            // Export the cluster's kubeconfig.
            ctx.export("kubeconfig", cluster.kubeconfig());
        }
    }
    
    name: aws-eks-cluster-default-yaml
    runtime: yaml
    description: An example that creates an EKS cluster with default configuration.
    resources:
      # Create an EKS cluster with the default configuration.
      cluster:
        type: eks:Cluster
    outputs:
      # Export the cluster's kubeconfig.
      kubeconfig: ${cluster.kubeconfig}
    

    This cluster uses reasonable defaults, like placing the cluster into your default VPC with a CNI interface, using AWS IAM Authenticator to leverage IAM for secure access to your cluster, and using two t2.medium nodes.

    After running pulumi up, the resulting cluster’s kubeconfig file is exported for you to use:

    $ pulumi up
    Updating (dev):
    
         Type                       Name                            Status
     +   pulumi:pulumi:Stack        eks-cluster-dev                 created
     +   └─ eks:index:Cluster       my-cluster                      created
         ... dozens of resources omitted ...
    
    Outputs:
        kubeconfig: {
            apiVersion     : "v1"
            clusters       : [
                [0]: {
                    cluster: {
                        certificate-authority-data: "...",
                        server                    : "https://D34E7144F46CB.sk1.us-west-2.eks.amazonaws.com"
                    }
                    name   : "kubernetes"
                }
            ]
            contexts       : [
                [0]: {
                    context: {
                        cluster: "kubernetes"
                        user   : "aws"
                    }
                    name   : "aws"
                }
            ]
            current-context: "aws"
            kind           : "Config"
            users          : [
                [0]: {
                    name: "aws"
                    user: {
                        exec: {
                            apiVersion: "client.authentication.k8s.io/v1beta1"
                            args      : [
                                [0]: "token"
                                [1]: "-i"
                                [2]: "my-cluster-eksCluster-22c2275"
                            ]
                            command   : "aws-iam-authenticator"
                        }
                    }
                }
            ]
        }
    
    Resources:
        + 43 created
    
    Duration: 11m26s
    

    Take this file and use it with the kubectl CLI:

    $ pulumi stack output kubeconfig > kubeconfig.yml
    $ KUBECONFIG=./kubeconfig.yml kubectl get nodes
    NAME                                         STATUS    ROLES     AGE       VERSION
    ip-172-31-29-62.us-west-2.compute.internal   Ready     <none>    1m       v1.12.7
    ip-172-31-40-32.us-west-2.compute.internal   Ready     <none>    2m       v1.12.7
    

    By default, Pulumi targets clusters based on your local kubeconfig, the same way kubectl does. If your kubectl client is set up to talk to your EKS cluster, deployments target it. You can also deploy into any Kubernetes cluster created in your Pulumi program, including the one created in Provisioning a new EKS cluster. This is because each Kubernetes object specification accepts an optional “provider” that can programmatically specify a kubeconfig to use.

    This is done by instantiating a new kubernetes.Provider object, and providing one or many of these properties:

    • cluster: A cluster name to target, if there are many in your kubeconfig to choose from.
    • context: The name of the kubeconfig context to use, if there are many to choose from.
    • kubeconfig: The contents of a kubeconfig file, or the path to one, to use instead of your local machine’s.

    From here, you have a fully functioning EKS cluster in Amazon to deploy Kubernetes applications to. Any existing tools work here, including kubectl, Helm, and other CI/CD products. Pulumi also lets you define Kubernetes application-level objects and configuration in code. For instance, you can deploy a canary to your EKS cluster in the same program to verify the cluster works as part of pulumi up:

    import * as pulumi from "@pulumi/pulumi";
    import * as eks from "@pulumi/eks";
    import * as kubernetes from "@pulumi/kubernetes";
    
    // Create an EKS cluster with the default configuration.
    const cluster = new eks.Cluster("cluster", {});
    const eksProvider = new kubernetes.Provider("eks-provider", { kubeconfig: cluster.kubeconfigJson });
    
    // Deploy a small canary service (NGINX), to test that the cluster is working.
    const myDeployment = new kubernetes.apps.v1.Deployment("my-deployment", {
        metadata: {
            labels: {
                appClass: "my-deployment",
            },
        },
        spec: {
            replicas: 2,
            selector: {
                matchLabels: {
                    appClass: "my-deployment",
                },
            },
            template: {
                metadata: {
                    labels: {
                        appClass: "my-deployment",
                    },
                },
                spec: {
                    containers: [
                        {
                            name: "my-deployment",
                            image: "nginx",
                            ports: [
                                {
                                    name: "http",
                                    containerPort: 80,
                                },
                            ],
                        },
                    ],
                },
            },
        },
    }, {
        provider: eksProvider,
    });
    const myService = new kubernetes.core.v1.Service("my-service", {
        metadata: {
            labels: {
                appClass: "my-deployment",
            },
        },
        spec: {
            type: "LoadBalancer",
            ports: [
                {
                    port: 80,
                    targetPort: "http",
                },
            ],
            selector: {
                appClass: "my-deployment",
            },
        },
    }, {
        provider: eksProvider,
    });
    
    // Export the cluster's kubeconfig.
    export const kubeconfig = cluster.kubeconfig;
    // Export the URL for the load balanced service.
    export const url = myService.status.apply(status => status?.loadBalancer?.ingress[0]?.hostname);
    
    import pulumi
    import pulumi_eks as eks
    import pulumi_kubernetes as kubernetes
    
    # Create an EKS cluster with the default configuration.
    cluster = eks.Cluster("cluster")
    eks_provider = kubernetes.Provider("eks-provider", kubeconfig=cluster.kubeconfig_json)
    # Deploy a small canary service (NGINX), to test that the cluster is working.
    my_deployment = kubernetes.apps.v1.Deployment("my-deployment",
        metadata=kubernetes.meta.v1.ObjectMetaArgs(
            labels={
                "appClass": "my-deployment",
            },
        ),
        spec=kubernetes.apps.v1.DeploymentSpecArgs(
            replicas=2,
            selector=kubernetes.meta.v1.LabelSelectorArgs(
                match_labels={
                    "appClass": "my-deployment",
                },
            ),
            template=kubernetes.core.v1.PodTemplateSpecArgs(
                metadata=kubernetes.meta.v1.ObjectMetaArgs(
                    labels={
                        "appClass": "my-deployment",
                    },
                ),
                spec=kubernetes.core.v1.PodSpecArgs(
                    containers=[kubernetes.core.v1.ContainerArgs(
                        name="my-deployment",
                        image="nginx",
                        ports=[kubernetes.core.v1.ContainerPortArgs(
                            name="http",
                            container_port=80,
                        )],
                    )],
                ),
            ),
        ),
        opts=pulumi.ResourceOptions(provider=eks_provider))
    my_service = kubernetes.core.v1.Service("my-service",
        metadata=kubernetes.meta.v1.ObjectMetaArgs(
            labels={
                "appClass": "my-deployment",
            },
        ),
        spec=kubernetes.core.v1.ServiceSpecArgs(
            type="LoadBalancer",
            ports=[kubernetes.core.v1.ServicePortArgs(
                port=80,
                target_port="http",
            )],
            selector={
                "appClass": "my-deployment",
            },
        ),
        opts=pulumi.ResourceOptions(provider=eks_provider))
    
    # Export the cluster's kubeconfig.
    pulumi.export("kubeconfig", cluster.kubeconfig)
    # Export the URL for the load balanced service.
    pulumi.export("url", my_service.status.load_balancer.ingress[0].hostname)
    
    package main
    
    import (
    	"github.com/pulumi/pulumi-eks/sdk/v4/go/eks"
    	"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes"
    	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 {
    		// Create an EKS cluster with the default configuration.
    		cluster, err := eks.NewCluster(ctx, "cluster", nil)
    		if err != nil {
    			return err
    		}
    		eksProvider, err := kubernetes.NewProvider(ctx, "eks-provider", &kubernetes.ProviderArgs{
    			Kubeconfig: cluster.KubeconfigJson,
    		})
    		if err != nil {
    			return err
    		}
    		// Deploy a small canary service (NGINX), to test that the cluster is working.
    		_, err = appsv1.NewDeployment(ctx, "my-deployment", &appsv1.DeploymentArgs{
    			Metadata: &metav1.ObjectMetaArgs{
    				Labels: pulumi.StringMap{
    					"appClass": pulumi.String("my-deployment"),
    				},
    			},
    			Spec: &appsv1.DeploymentSpecArgs{
    				Replicas: pulumi.Int(2),
    				Selector: &metav1.LabelSelectorArgs{
    					MatchLabels: pulumi.StringMap{
    						"appClass": pulumi.String("my-deployment"),
    					},
    				},
    				Template: &corev1.PodTemplateSpecArgs{
    					Metadata: &metav1.ObjectMetaArgs{
    						Labels: pulumi.StringMap{
    							"appClass": pulumi.String("my-deployment"),
    						},
    					},
    					Spec: &corev1.PodSpecArgs{
    						Containers: corev1.ContainerArray{
    							&corev1.ContainerArgs{
    								Name:  pulumi.String("my-deployment"),
    								Image: pulumi.String("nginx"),
    								Ports: corev1.ContainerPortArray{
    									&corev1.ContainerPortArgs{
    										Name:          pulumi.String("http"),
    										ContainerPort: pulumi.Int(80),
    									},
    								},
    							},
    						},
    					},
    				},
    			},
    		}, pulumi.Provider(eksProvider))
    		if err != nil {
    			return err
    		}
    		myService, err := corev1.NewService(ctx, "my-service", &corev1.ServiceArgs{
    			Metadata: &metav1.ObjectMetaArgs{
    				Labels: pulumi.StringMap{
    					"appClass": pulumi.String("my-deployment"),
    				},
    			},
    			Spec: &corev1.ServiceSpecArgs{
    				Type: pulumi.String("LoadBalancer"),
    				Ports: corev1.ServicePortArray{
    					&corev1.ServicePortArgs{
    						Port:       pulumi.Int(80),
    						TargetPort: pulumi.Any("http"),
    					},
    				},
    				Selector: pulumi.StringMap{
    					"appClass": pulumi.String("my-deployment"),
    				},
    			},
    		}, pulumi.Provider(eksProvider))
    		if err != nil {
    			return err
    		}
    		// Export the cluster's kubeconfig.
    		ctx.Export("kubeconfig", cluster.Kubeconfig)
    		// Export the URL for the load balanced service.
    		ctx.Export("url", myService.Status.ApplyT(func(status interface{}) (string, error) {
    			return *status.(*corev1.ServiceStatus).LoadBalancer.Ingress[0].Hostname, nil
    		}).(pulumi.StringOutput))
    		return nil
    	})
    }
    
    using System.Collections.Generic;
    using Pulumi;
    using Eks = Pulumi.Eks;
    using Kubernetes = Pulumi.Kubernetes;
    
    return await Deployment.RunAsync(() =>
    {
        // Create an EKS cluster with the default configuration.
        var cluster = new Eks.Cluster("cluster");
    
        var eksProvider = new Kubernetes.Provider("eks-provider", new()
        {
            KubeConfig = cluster.KubeconfigJson,
        });
    
        // Deploy a small canary service (NGINX), to test that the cluster is working.
        var myDeployment = new Kubernetes.Apps.V1.Deployment("my-deployment", new()
        {
            Metadata = new Kubernetes.Types.Inputs.Meta.V1.ObjectMetaArgs
            {
                Labels =
                {
                    { "appClass", "my-deployment" },
                },
            },
            Spec = new Kubernetes.Types.Inputs.Apps.V1.DeploymentSpecArgs
            {
                Replicas = 2,
                Selector = new Kubernetes.Types.Inputs.Meta.V1.LabelSelectorArgs
                {
                    MatchLabels =
                    {
                        { "appClass", "my-deployment" },
                    },
                },
                Template = new Kubernetes.Types.Inputs.Core.V1.PodTemplateSpecArgs
                {
                    Metadata = new Kubernetes.Types.Inputs.Meta.V1.ObjectMetaArgs
                    {
                        Labels =
                        {
                            { "appClass", "my-deployment" },
                        },
                    },
                    Spec = new Kubernetes.Types.Inputs.Core.V1.PodSpecArgs
                    {
                        Containers = new[]
                        {
                            new Kubernetes.Types.Inputs.Core.V1.ContainerArgs
                            {
                                Name = "my-deployment",
                                Image = "nginx",
                                Ports = new[]
                                {
                                    new Kubernetes.Types.Inputs.Core.V1.ContainerPortArgs
                                    {
                                        Name = "http",
                                        ContainerPortValue = 80,
                                    },
                                },
                            },
                        },
                    },
                },
            },
        }, new CustomResourceOptions
        {
            Provider = eksProvider,
        });
    
        var myService = new Kubernetes.Core.V1.Service("my-service", new()
        {
            Metadata = new Kubernetes.Types.Inputs.Meta.V1.ObjectMetaArgs
            {
                Labels =
                {
                    { "appClass", "my-deployment" },
                },
            },
            Spec = new Kubernetes.Types.Inputs.Core.V1.ServiceSpecArgs
            {
                Type = "LoadBalancer",
                Ports = new[]
                {
                    new Kubernetes.Types.Inputs.Core.V1.ServicePortArgs
                    {
                        Port = 80,
                        TargetPort = "http",
                    },
                },
                Selector =
                {
                    { "appClass", "my-deployment" },
                },
            },
        }, new CustomResourceOptions
        {
            Provider = eksProvider,
        });
    
        return new Dictionary<string, object?>
        {
            // Export the cluster's kubeconfig.
            ["kubeconfig"] = cluster.Kubeconfig,
            // Export the URL for the load balanced service.
            ["url"] = myService.Status.Apply(status => status?.LoadBalancer?.Ingress[0]?.Hostname),
        };
    });
    
    package myproject;
    
    import com.pulumi.Context;
    import com.pulumi.Pulumi;
    import com.pulumi.core.Output;
    import com.pulumi.eks.Cluster;
    import com.pulumi.kubernetes.Provider;
    import com.pulumi.kubernetes.ProviderArgs;
    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.ServicePortArgs;
    import com.pulumi.kubernetes.core.v1.inputs.ContainerArgs;
    import com.pulumi.kubernetes.core.v1.inputs.ContainerPortArgs;
    import com.pulumi.kubernetes.core.v1.inputs.PodSpecArgs;
    import com.pulumi.kubernetes.core.v1.Service;
    import com.pulumi.kubernetes.core.v1.ServiceArgs;
    import com.pulumi.kubernetes.core.v1.inputs.ServiceSpecArgs;
    import com.pulumi.resources.CustomResourceOptions;
    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) {
            // Create an EKS cluster with the default configuration.
            var cluster = new Cluster("cluster");
    
            var eksProvider = new Provider("eksProvider", ProviderArgs.builder()
                .kubeconfig(cluster.kubeconfigJson())
                .build());
    
            // Deploy a small canary service (NGINX), to test that the cluster is working.
            var myDeployment = new Deployment("myDeployment", DeploymentArgs.builder()
                .metadata(ObjectMetaArgs.builder()
                    .labels(Map.of("appClass", "my-deployment"))
                    .build())
                .spec(DeploymentSpecArgs.builder()
                    .replicas(2)
                    .selector(LabelSelectorArgs.builder()
                        .matchLabels(Map.of("appClass", "my-deployment"))
                        .build())
                    .template(PodTemplateSpecArgs.builder()
                        .metadata(ObjectMetaArgs.builder()
                            .labels(Map.of("appClass", "my-deployment"))
                            .build())
                        .spec(PodSpecArgs.builder()
                            .containers(ContainerArgs.builder()
                                .name("my-deployment")
                                .image("nginx")
                                .ports(ContainerPortArgs.builder()
                                    .name("http")
                                    .containerPort(80)
                                    .build())
                                .build())
                            .build())
                        .build())
                    .build())
                .build(), CustomResourceOptions.builder()
                    .provider(eksProvider)
                    .build());
    
            var myService = new Service("myService", ServiceArgs.builder()
                .metadata(ObjectMetaArgs.builder()
                    .labels(Map.of("appClass", "my-deployment"))
                    .build())
                .spec(ServiceSpecArgs.builder()
                    .type("LoadBalancer")
                    .ports(ServicePortArgs.builder()
                        .port(80)
                        .targetPort("http")
                        .build())
                    .selector(Map.of("appClass", "my-deployment"))
                    .build())
                .build(), CustomResourceOptions.builder()
                    .provider(eksProvider)
                    .build());
    
            // Export the cluster's kubeconfig.
            ctx.export("kubeconfig", cluster.kubeconfig());
            // Export the URL for the load balanced service.
            ctx.export("url", myService.status()
                .applyValue(status -> status.orElseThrow().loadBalancer().orElseThrow())
                .applyValue(status -> status.ingress().get(0).hostname().orElseThrow()));
        }
    }
    
    name: aws-eks-cluster-k8s-canary-yaml
    runtime: yaml
    description: An example that deploys an EKS cluster and a canary NGINX service.
    resources:
      # Create an EKS cluster with the default configuration.
      cluster:
        type: eks:Cluster
      eks-provider:
        type: pulumi:providers:kubernetes
        properties:
          kubeconfig: ${cluster.kubeconfigJson}
      # Deploy a small canary service (NGINX), to test that the cluster is working.
      my-deployment:
        type: kubernetes:apps/v1:Deployment
        properties:
          metadata:
            labels:
              appClass: my-deployment
          spec:
            replicas: 2
            selector:
              matchLabels:
                appClass: my-deployment
            template:
              metadata:
                labels:
                  appClass: my-deployment
              spec:
                containers:
                  - name: my-deployment
                    image: nginx
                    ports:
                      - name: http
                        containerPort: 80
        options:
          provider: ${eks-provider}
      my-service:
        type: kubernetes:core/v1:Service
        properties:
          metadata:
            labels:
              appClass: my-deployment
          spec:
            type: LoadBalancer
            ports:
              - port: 80
                targetPort: http
            selector:
              appClass: my-deployment
        options:
          provider: ${eks-provider}
    outputs:
      # Export the cluster's kubeconfig.
      kubeconfig: ${cluster.kubeconfig}
      # Export the URL for the load balanced service.
      url: ${my-service.status.loadBalancer.ingress[0].hostname}
    

    Deploying this on top of an existing EKS cluster produces a diff containing only the new Kubernetes Deployment and Service objects, and prints the resulting URL for the load balanced service. Use that URL to confirm the Pods have started and to check the health of your cluster:

    $ pulumi stack output kubeconfig > kubeconfig.yml
    $ KUBECONFIG=./kubeconfig.yml kubectl get po
    NAME                                 READY     STATUS    RESTARTS   AGE
    my-app-de-6gfz4ap5-dc8c6584f-6xmcl   1/1       Running   0          3m
    my-app-de-6gfz4ap5-dc8c6584f-wzlf9   1/1       Running   0          3m
    $ curl http://$(pulumi stack output url)
    <html>
    <head>
    <title>Welcome to nginx!</title>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    </body>
    </html>
    

    Changing the default settings on an EKS cluster

    The above example showed using the default settings for your EKS cluster. Override them by passing arguments to the constructor. For instance, this example changes the desired capacity and enables certain cluster logging types:

    import * as pulumi from "@pulumi/pulumi";
    import * as eks from "@pulumi/eks";
    
    // Create an EKS cluster with a modified configuration.
    const cluster = new eks.Cluster("cluster", {
        desiredCapacity: 5,
        minSize: 3,
        maxSize: 5,
        enabledClusterLogTypes: [
            "api",
            "audit",
            "authenticator",
        ],
    });
    
    // Export the cluster's kubeconfig.
    export const kubeconfig = cluster.kubeconfig;
    
    import pulumi
    import pulumi_eks as eks
    
    # Create an EKS cluster with a modified configuration.
    cluster = eks.Cluster("cluster",
        desired_capacity=5,
        min_size=3,
        max_size=5,
        enabled_cluster_log_types=[
            "api",
            "audit",
            "authenticator",
        ])
    
    # Export the cluster's kubeconfig.
    pulumi.export("kubeconfig", cluster.kubeconfig)
    
    package main
    
    import (
    	"github.com/pulumi/pulumi-eks/sdk/v4/go/eks"
    	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    )
    
    func main() {
    	pulumi.Run(func(ctx *pulumi.Context) error {
    		// Create an EKS cluster with a modified configuration.
    		cluster, err := eks.NewCluster(ctx, "cluster", &eks.ClusterArgs{
    			DesiredCapacity: pulumi.Int(5),
    			MinSize:         pulumi.Int(3),
    			MaxSize:         pulumi.Int(5),
    			EnabledClusterLogTypes: pulumi.StringArray{
    				pulumi.String("api"),
    				pulumi.String("audit"),
    				pulumi.String("authenticator"),
    			},
    		})
    		if err != nil {
    			return err
    		}
    
    		// Export the cluster's kubeconfig.
    		ctx.Export("kubeconfig", cluster.Kubeconfig)
    		return nil
    	})
    }
    
    using System.Collections.Generic;
    using Pulumi;
    using Eks = Pulumi.Eks;
    
    return await Deployment.RunAsync(() =>
    {
        // Create an EKS cluster with a modified configuration.
        var cluster = new Eks.Cluster("cluster", new()
        {
            DesiredCapacity = 5,
            MinSize = 3,
            MaxSize = 5,
            EnabledClusterLogTypes = new[]
            {
                "api",
                "audit",
                "authenticator",
            },
        });
    
        return new Dictionary<string, object?>
        {
            // Export the cluster's kubeconfig.
            ["kubeconfig"] = cluster.Kubeconfig,
        };
    });
    
    package myproject;
    
    import com.pulumi.Context;
    import com.pulumi.Pulumi;
    import com.pulumi.core.Output;
    import com.pulumi.eks.Cluster;
    import com.pulumi.eks.ClusterArgs;
    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) {
            // Create an EKS cluster with a modified configuration.
            var cluster = new Cluster("cluster", ClusterArgs.builder()
                .desiredCapacity(5)
                .minSize(3)
                .maxSize(5)
                .enabledClusterLogTypes(
                    "api",
                    "audit",
                    "authenticator")
                .build());
    
            // Export the cluster's kubeconfig.
            ctx.export("kubeconfig", cluster.kubeconfig());
        }
    }
    
    name: aws-eks-cluster-settings-yaml
    runtime: yaml
    description: An example that creates an EKS cluster with modified settings.
    resources:
      # Create an EKS cluster with a modified configuration.
      cluster:
        type: eks:Cluster
        properties:
          desiredCapacity: 5
          minSize: 3
          maxSize: 5
          enabledClusterLogTypes:
            - api
            - audit
            - authenticator
    outputs:
      # Export the cluster's kubeconfig.
      kubeconfig: ${cluster.kubeconfig}
    

    For a full list of options that you may set on your cluster, see the API documentation. Many common cases are described below.

    Configuring your EKS cluster’s networking

    By default, your EKS cluster is put into your region’s default VPC. This is a reasonable default, however this is configurable if you want specific network isolation or to place your cluster work nodes on private subnets. This works in conjunction with the Pulumi VPC guide, which makes configuring VPCs easier.

    This example creates a new VPC and creates the EKS cluster inside of it:

    import * as pulumi from "@pulumi/pulumi";
    import * as awsx from "@pulumi/awsx";
    import * as eks from "@pulumi/eks";
    
    // Create a VPC for our cluster.
    const vpc = new awsx.ec2.Vpc("vpc", {});
    
    // Create an EKS cluster inside of the VPC.
    const cluster = new eks.Cluster("cluster", {
        vpcId: vpc.vpcId,
        publicSubnetIds: vpc.publicSubnetIds,
        privateSubnetIds: vpc.privateSubnetIds,
        nodeAssociatePublicIpAddress: false,
    });
    
    // Export the cluster's kubeconfig.
    export const kubeconfig = cluster.kubeconfig;
    
    import pulumi
    import pulumi_awsx as awsx
    import pulumi_eks as eks
    
    # Create a VPC for our cluster.
    vpc = awsx.ec2.Vpc("vpc")
    
    # Create an EKS cluster inside of the VPC.
    cluster = eks.Cluster("cluster",
        vpc_id=vpc.vpc_id,
        public_subnet_ids=vpc.public_subnet_ids,
        private_subnet_ids=vpc.private_subnet_ids,
        node_associate_public_ip_address=False)
    
    # Export the cluster's kubeconfig.
    pulumi.export("kubeconfig", cluster.kubeconfig)
    
    package main
    
    import (
    	"github.com/pulumi/pulumi-awsx/sdk/v3/go/awsx/ec2"
    	"github.com/pulumi/pulumi-eks/sdk/v4/go/eks"
    	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    )
    
    func main() {
    	pulumi.Run(func(ctx *pulumi.Context) error {
    		// Create a VPC for our cluster.
    		vpc, err := ec2.NewVpc(ctx, "vpc", nil)
    		if err != nil {
    			return err
    		}
    
    		// Create an EKS cluster inside of the VPC.
    		cluster, err := eks.NewCluster(ctx, "cluster", &eks.ClusterArgs{
    			VpcId:                        vpc.VpcId,
    			PublicSubnetIds:              vpc.PublicSubnetIds,
    			PrivateSubnetIds:             vpc.PrivateSubnetIds,
    			NodeAssociatePublicIpAddress: pulumi.BoolRef(false),
    		})
    		if err != nil {
    			return err
    		}
    
    		// Export the cluster's kubeconfig.
    		ctx.Export("kubeconfig", cluster.Kubeconfig)
    		return nil
    	})
    }
    
    using System.Collections.Generic;
    using Pulumi;
    using Awsx = Pulumi.Awsx;
    using Eks = Pulumi.Eks;
    
    return await Deployment.RunAsync(() =>
    {
        // Create a VPC for our cluster.
        var vpc = new Awsx.Ec2.Vpc("vpc");
    
        // Create an EKS cluster inside of the VPC.
        var cluster = new Eks.Cluster("cluster", new()
        {
            VpcId = vpc.VpcId,
            PublicSubnetIds = vpc.PublicSubnetIds,
            PrivateSubnetIds = vpc.PrivateSubnetIds,
            NodeAssociatePublicIpAddress = false,
        });
    
        // Export the cluster's kubeconfig.
        return new Dictionary<string, object?>
        {
            ["kubeconfig"] = cluster.Kubeconfig,
        };
    });
    
    package myproject;
    
    import com.pulumi.Context;
    import com.pulumi.Pulumi;
    import com.pulumi.core.Output;
    import com.pulumi.awsx.ec2.Vpc;
    import com.pulumi.eks.Cluster;
    import com.pulumi.eks.ClusterArgs;
    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) {
            // Create a VPC for our cluster.
            var vpc = new Vpc("vpc");
    
            // Create an EKS cluster inside of the VPC.
            var cluster = new Cluster("cluster", ClusterArgs.builder()
                .vpcId(vpc.vpcId())
                .publicSubnetIds(vpc.publicSubnetIds())
                .privateSubnetIds(vpc.privateSubnetIds())
                .nodeAssociatePublicIpAddress(false)
                .build());
    
            // Export the cluster's kubeconfig.
            ctx.export("kubeconfig", cluster.kubeconfig());
        }
    }
    
    name: aws-eks-cluster-yaml
    runtime: yaml
    description: An example that deploys a Kubernetes cluster on AWS.
    resources:
      # Create a VPC for our cluster.
      vpc:
        type: awsx:ec2:Vpc
      # Create an EKS cluster within the VPC.
      cluster:
        type: eks:Cluster
        properties:
          vpcId: ${vpc.vpcId}
          publicSubnetIds: ${vpc.publicSubnetIds}
          privateSubnetIds: ${vpc.privateSubnetIds}
          nodeAssociatePublicIpAddress: false
    outputs:
      # Export the cluster's kubeconfig.
      kubeconfig: ${cluster.kubeconfig}
    

    When you create an Amazon EKS cluster, you specify the Amazon VPC subnets for your cluster to use. These must be in at least two Availability Zones. We recommend a network architecture that uses private subnets for your worker nodes and public subnets for Kubernetes to create Internet-facing load balancers within. When you create your cluster, specify all of the subnets that will host resources for your cluster (including workers and load balancers).

    In the above example, both the private and public subnets from the VPC are passed to the cluster. The EKS package figures out which ones are public and which ones are private, and creates the worker nodes inside only the private subnets if any are specified. EKS tags the provided subnets so that Kubernetes can discover them. If you need additional control over how load balancers are allocated to subnets, you can attach additional subnet tags yourself, as outlined in Amazon EKS networking requirements for VPC and subnets.

    Note that by default the eks.Cluster does the same as what is described here, but inside of the default VPC in your account, rather than a custom VPC as shown in this example.

    Configuring your EKS cluster’s worker nodes and node groups

    Worker machines in Kubernetes are called nodes. Amazon EKS worker nodes run in your AWS account and connect to your cluster’s control plane via the cluster API server endpoint. These are standard Amazon EC2 instances, and you are billed for them based on normal EC2 On-Demand prices. By default, an EKS-optimized Amazon Linux AMI is used as the base image for EKS worker nodes. It comes preconfigured with the container runtime, kubelet, and the other components a node needs to register with the cluster.

    Nodes exist in groups and you can create multiple groups for workloads that require it. By default, your EKS cluster is given a default node group, with the instance sizes and counts that you specify (or the defaults of two t2.medium instances otherwise). The latest version of Kubernetes available is used by default.

    If you would like to disable the creation of a default node group, and instead rely on creating your own, pass skipDefaultNodeGroup as true to the eks.Cluster constructor. Additional node groups may then be created by creating an eks.NodeGroupV2 explicitly. In both cases, you would likely want to configure IAM roles for your worker nodes explicitly, which can be supplied to your EKS cluster using the instanceRole or instanceRoles properties.

    For instance, suppose you want two node groups: one for fixed, known workloads, and another that is burstable and might use more expensive compute, but which can be scaled down when possible (possibly to zero). Skip the default node group, and create your own node groups:

    import * as pulumi from "@pulumi/pulumi";
    import * as aws from "@pulumi/aws";
    import * as eks from "@pulumi/eks";
    
    const managedPolicyArns = [
        "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
        "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
        "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",
    ];
    const assumeRolePolicy = JSON.stringify({
        Version: "2012-10-17",
        Statement: [
            {
                Action: "sts:AssumeRole",
                Effect: "Allow",
                Principal: {
                    Service: "ec2.amazonaws.com",
                },
            },
        ],
    });
    const role1 = new aws.iam.Role("role1", {
        assumeRolePolicy: assumeRolePolicy,
        managedPolicyArns: managedPolicyArns,
    });
    const role2 = new aws.iam.Role("role2", {
        assumeRolePolicy: assumeRolePolicy,
        managedPolicyArns: managedPolicyArns,
    });
    const instanceProfile1 = new aws.iam.InstanceProfile("instanceProfile1", { role: role1.name });
    const instanceProfile2 = new aws.iam.InstanceProfile("instanceProfile2", { role: role2.name });
    const cluster = new eks.Cluster("cluster", {
        skipDefaultNodeGroup: true,
        instanceRoles: [role1, role2],
    });
    const fixedNodeGroup = new eks.NodeGroupV2("fixedNodeGroup", {
        cluster: cluster,
        instanceType: "t2.medium",
        desiredCapacity: 2,
        minSize: 1,
        maxSize: 3,
        spotPrice: "1",
        labels: {
            ondemand: "true",
        },
        instanceProfile: instanceProfile1,
    });
    const spotNodeGroup = new eks.NodeGroupV2("spotNodeGroup", {
        cluster: cluster,
        instanceType: "t2.medium",
        desiredCapacity: 1,
        minSize: 1,
        maxSize: 2,
        labels: {
            preemptible: "true",
        },
        instanceProfile: instanceProfile2,
    });
    export const kubeconfig = cluster.kubeconfig;
    
    import pulumi
    import json
    import pulumi_aws as aws
    import pulumi_eks as eks
    
    managed_policy_arns = [
        "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
        "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
        "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",
    ]
    assume_role_policy = json.dumps({
        "Version": "2012-10-17",
        "Statement": [{
            "Action": "sts:AssumeRole",
            "Effect": "Allow",
            "Principal": {
                "Service": "ec2.amazonaws.com",
            },
        }],
    })
    role1 = aws.iam.Role("role1",
        assume_role_policy=assume_role_policy,
        managed_policy_arns=managed_policy_arns)
    role2 = aws.iam.Role("role2",
        assume_role_policy=assume_role_policy,
        managed_policy_arns=managed_policy_arns)
    instance_profile1 = aws.iam.InstanceProfile("instanceProfile1", role=role1.name)
    instance_profile2 = aws.iam.InstanceProfile("instanceProfile2", role=role2.name)
    cluster = eks.Cluster("cluster",
        skip_default_node_group=True,
        instance_roles=[role1, role2])
    fixed_node_group = eks.NodeGroupV2("fixedNodeGroup",
        cluster=cluster,
        instance_type="t2.medium",
        desired_capacity=2,
        min_size=1,
        max_size=3,
        spot_price="1",
        labels={
            "ondemand": "true",
        },
        instance_profile=instance_profile1)
    spot_node_group = eks.NodeGroupV2("spotNodeGroup",
        cluster=cluster,
        instance_type="t2.medium",
        desired_capacity=1,
        min_size=1,
        max_size=2,
        labels={
            "preemptible": "true",
        },
        instance_profile=instance_profile2)
    pulumi.export("kubeconfig", cluster.kubeconfig)
    
    package main
    
    import (
    	"encoding/json"
    
    	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
    	"github.com/pulumi/pulumi-eks/sdk/v4/go/eks"
    	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    )
    
    func main() {
    	pulumi.Run(func(ctx *pulumi.Context) error {
    		managedPolicyArns := []string{
    			"arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
    			"arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
    			"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",
    		}
    		tmpJSON0, err := json.Marshal(map[string]interface{}{
    			"Version": "2012-10-17",
    			"Statement": []map[string]interface{}{
    				map[string]interface{}{
    					"Action": "sts:AssumeRole",
    					"Effect": "Allow",
    					"Sid":    nil,
    					"Principal": map[string]interface{}{
    						"Service": "ec2.amazonaws.com",
    					},
    				},
    			},
    		})
    		if err != nil {
    			return err
    		}
    		json0 := string(tmpJSON0)
    		assumeRolePolicy := json0
    		role1, err := iam.NewRole(ctx, "role1", &iam.RoleArgs{
    			AssumeRolePolicy:  pulumi.String(assumeRolePolicy),
    			ManagedPolicyArns: pulumi.ToStringArray(managedPolicyArns),
    		})
    		if err != nil {
    			return err
    		}
    		role2, err := iam.NewRole(ctx, "role2", &iam.RoleArgs{
    			AssumeRolePolicy:  pulumi.String(assumeRolePolicy),
    			ManagedPolicyArns: pulumi.ToStringArray(managedPolicyArns),
    		})
    		if err != nil {
    			return err
    		}
    		instanceProfile1, err := iam.NewInstanceProfile(ctx, "instanceProfile1", &iam.InstanceProfileArgs{
    			Role: role1.Name,
    		})
    		if err != nil {
    			return err
    		}
    		instanceProfile2, err := iam.NewInstanceProfile(ctx, "instanceProfile2", &iam.InstanceProfileArgs{
    			Role: role2.Name,
    		})
    		if err != nil {
    			return err
    		}
    		cluster, err := eks.NewCluster(ctx, "cluster", &eks.ClusterArgs{
    			SkipDefaultNodeGroup: pulumi.BoolRef(true),
    			InstanceRoles:        iam.RoleArray{
    				role1,
    				role2,
    			},
    		})
    		if err != nil {
    			return err
    		}
    		_, err = eks.NewNodeGroupV2(ctx, "fixedNodeGroup", &eks.NodeGroupV2Args{
    			Cluster:         cluster,
    			InstanceType:    pulumi.String("t2.medium"),
    			DesiredCapacity: pulumi.Int(2),
    			MinSize:         pulumi.Int(1),
    			MaxSize:         pulumi.Int(3),
    			SpotPrice:       pulumi.String("1"),
    			Labels: pulumi.StringMap{
    				"ondemand": pulumi.String("true"),
    			},
    			InstanceProfile: instanceProfile1,
    		})
    		if err != nil {
    			return err
    		}
    		_, err = eks.NewNodeGroupV2(ctx, "spotNodeGroup", &eks.NodeGroupV2Args{
    			Cluster:         cluster,
    			InstanceType:    pulumi.String("t2.medium"),
    			DesiredCapacity: pulumi.Int(1),
    			MinSize:         pulumi.Int(1),
    			MaxSize:         pulumi.Int(2),
    			Labels: pulumi.StringMap{
    				"preemptible": pulumi.String("true"),
    			},
    			InstanceProfile: instanceProfile2,
    		})
    		if err != nil {
    			return err
    		}
    		ctx.Export("kubeconfig", cluster.Kubeconfig)
    		return nil
    	})
    }
    
    using System.Collections.Generic;
    using System.Text.Json;
    using Pulumi;
    using Aws = Pulumi.Aws;
    using Eks = Pulumi.Eks;
    
    return await Deployment.RunAsync(() =>
    {
        var managedPolicyArns = new[]
        {
            "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
            "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
            "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",
        };
    
        var assumeRolePolicy = JsonSerializer.Serialize(new Dictionary<string, object?>
        {
            ["Version"] = "2012-10-17",
            ["Statement"] = new[]
            {
                new Dictionary<string, object?>
                {
                    ["Action"] = "sts:AssumeRole",
                    ["Effect"] = "Allow",
                    ["Sid"] = null,
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["Service"] = "ec2.amazonaws.com",
                    },
                },
            },
        });
    
        var role1 = new Aws.Iam.Role("role1", new()
        {
            AssumeRolePolicy = assumeRolePolicy,
            ManagedPolicyArns = managedPolicyArns,
        });
    
        var role2 = new Aws.Iam.Role("role2", new()
        {
            AssumeRolePolicy = assumeRolePolicy,
            ManagedPolicyArns = managedPolicyArns,
        });
    
        var instanceProfile1 = new Aws.Iam.InstanceProfile("instanceProfile1", new()
        {
            Role = role1.Name,
        });
    
        var instanceProfile2 = new Aws.Iam.InstanceProfile("instanceProfile2", new()
        {
            Role = role2.Name,
        });
    
        var cluster = new Eks.Cluster("cluster", new()
        {
            SkipDefaultNodeGroup = true,
            InstanceRoles = new[]
            {
                role1,
                role2,
            },
        });
    
        var fixedNodeGroup = new Eks.NodeGroupV2("fixedNodeGroup", new()
        {
            Cluster = cluster,
            InstanceType = "t2.medium",
            DesiredCapacity = 2,
            MinSize = 1,
            MaxSize = 3,
            SpotPrice = "1",
            Labels =
            {
                { "ondemand", "true" },
            },
            InstanceProfile = instanceProfile1,
        });
    
        var spotNodeGroup = new Eks.NodeGroupV2("spotNodeGroup", new()
        {
            Cluster = cluster,
            InstanceType = "t2.medium",
            DesiredCapacity = 1,
            MinSize = 1,
            MaxSize = 2,
            Labels =
            {
                { "preemptible", "true" },
            },
            InstanceProfile = instanceProfile2,
        });
    
        return new Dictionary<string, object?>
        {
            ["kubeconfig"] = cluster.Kubeconfig,
        };
    });
    
    package myproject;
    
    import com.pulumi.Context;
    import com.pulumi.Pulumi;
    import com.pulumi.core.Output;
    import com.pulumi.aws.iam.Role;
    import com.pulumi.aws.iam.RoleArgs;
    import com.pulumi.aws.iam.InstanceProfile;
    import com.pulumi.aws.iam.InstanceProfileArgs;
    import com.pulumi.eks.Cluster;
    import com.pulumi.eks.ClusterArgs;
    import com.pulumi.eks.NodeGroupV2;
    import com.pulumi.eks.NodeGroupV2Args;
    import static com.pulumi.codegen.internal.Serialization.*;
    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) {
            final var managedPolicyArns = List.of(
                "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
                "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
                "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
            );
    
            final var assumeRolePolicy = serializeJson(
                jsonObject(
                    jsonProperty("Version", "2012-10-17"),
                    jsonProperty("Statement", jsonArray(jsonObject(
                        jsonProperty("Action", "sts:AssumeRole"),
                        jsonProperty("Effect", "Allow"),
                        jsonProperty("Sid", ""),
                        jsonProperty("Principal", jsonObject(
                            jsonProperty("Service", "ec2.amazonaws.com")
                        ))
                    )))
                ));
    
            var role1 = new Role("role1", RoleArgs.builder()
                .assumeRolePolicy(assumeRolePolicy)
                .managedPolicyArns(managedPolicyArns)
                .build());
    
            var role2 = new Role("role2", RoleArgs.builder()
                .assumeRolePolicy(assumeRolePolicy)
                .managedPolicyArns(managedPolicyArns)
                .build());
    
            var instanceProfile1 = new InstanceProfile("instanceProfile1", InstanceProfileArgs.builder()
                .role(role1.name())
                .build());
    
            var instanceProfile2 = new InstanceProfile("instanceProfile2", InstanceProfileArgs.builder()
                .role(role2.name())
                .build());
    
            var cluster = new Cluster("cluster", ClusterArgs.builder()
                .skipDefaultNodeGroup(true)
                .instanceRoles(List.of(role1, role2))
                .build());
    
            var fixedNodeGroup = new NodeGroupV2("fixedNodeGroup", NodeGroupV2Args.builder()
                .cluster(cluster)
                .instanceType("t2.medium")
                .desiredCapacity(2)
                .minSize(1)
                .maxSize(3)
                .spotPrice("1")
                .labels(Map.of("ondemand", "true"))
                .instanceProfile(instanceProfile1)
                .build());
    
            var spotNodeGroup = new NodeGroupV2("spotNodeGroup", NodeGroupV2Args.builder()
                .cluster(cluster)
                .instanceType("t2.medium")
                .desiredCapacity(1)
                .minSize(1)
                .maxSize(2)
                .labels(Map.of("preemptible", "true"))
                .instanceProfile(instanceProfile2)
                .build());
    
            ctx.export("kubeconfig", cluster.kubeconfig());
        }
    }
    
    name: aws-eks-cluster-node-groups-yaml
    runtime: yaml
    description: An example that creates an EKS cluster with custom node groups.
    variables:
      managedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
        - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
      assumeRolePolicy:
        fn::toJSON:
          Version: 2012-10-17
          Statement:
            - Action: sts:AssumeRole
              Effect: Allow
              Sid: ""
              Principal:
                Service: ec2.amazonaws.com
    resources:
      # Create instance profiles for the two node groups.
      role1:
        type: aws:iam:Role
        properties:
          assumeRolePolicy: ${assumeRolePolicy}
          managedPolicyArns: ${managedPolicyArns}
      role2:
        type: aws:iam:Role
        properties:
          assumeRolePolicy: ${assumeRolePolicy}
          managedPolicyArns: ${managedPolicyArns}
      instanceProfile1:
        type: aws:iam:InstanceProfile
        properties:
          role: ${role1.name}
      instanceProfile2:
        type: aws:iam:InstanceProfile
        properties:
          role: ${role2.name}
      # Create an EKS cluster with the IAM roles, and with no default node group.
      cluster:
        type: eks:Cluster
        properties:
          skipDefaultNodeGroup: true
          instanceRoles:
            - ${role1}
            - ${role2}
      # Create a node group for fixed compute.
      fixedNodeGroup:
        type: eks:NodeGroupV2
        properties:
          cluster: ${cluster}
          instanceType: t2.medium
          desiredCapacity: 2
          minSize: 1
          maxSize: 3
          spotPrice: "1"
          labels:
            ondemand: true
          instanceProfile: ${instanceProfile1}
      # Create a preemptible node group using spot pricing for our ephemeral workloads.
      spotNodeGroup:
        type: eks:NodeGroupV2
        properties:
          cluster: ${cluster}
          instanceType: t2.medium
          desiredCapacity: 1
          minSize: 1
          maxSize: 2
          labels:
            preemptible: "true"
          instanceProfile: ${instanceProfile2}
    outputs:
      # Export the cluster's kubeconfig.
      kubeconfig: ${cluster.kubeconfig}
    

    After configuring such a cluster, ensure your workload’s pods are scheduled correctly on the right nodes, using a combination of node selectors, taints, and tolerations. For more information, see Assigning Pods to Nodes and Taints and Tolerations.

    Managing EKS cluster authentication with IAM

    When you create an Amazon EKS cluster, the IAM entity user or role (for example, for federated users) that creates the cluster is automatically granted system:masters permissions in the cluster’s RBAC configuration. To grant additional AWS users or roles the ability to interact with your cluster, you must edit the aws-auth ConfigMap within Kubernetes.

    The roleMappings property for your EKS cluster lets you configure custom IAM roles. For example, you can create different IAM roles for cluster admins, automation accounts (for CI/CD), and production roles, and supply them to roleMappings; this has the effect of placing them in the aws-auth ConfigMap for your cluster automatically. Pulumi also lets you configure Kubernetes objects, so that can also then create the RBAC cluster role bindings in your cluster to tie everything together.

    For a complete example of this in action, see Simplifying Kubernetes RBAC in Amazon EKS.

    Deploying Kubernetes apps to your EKS cluster

    Pulumi supports the entire Kubernetes object model in the @pulumi/kubernetes package. For more information on these object types, including Deployments, Services, and Pods, see Understanding Kubernetes Objects.

    With Pulumi, you describe your desired Kubernetes configuration, and pulumi up diffs the current state against what is desired, then drives the API server to bring your desired state into existence.

    For example, this program creates a simple load balanced NGINX service, exporting its URL:

    import * as pulumi from "@pulumi/pulumi";
    import * as kubernetes from "@pulumi/kubernetes";
    
    // Create an NGINX Deployment and load balanced Service.
    const myDeployment = new kubernetes.apps.v1.Deployment("my-deployment", {
        metadata: {
            labels: {
                appClass: "my-deployment",
            },
        },
        spec: {
            replicas: 2,
            selector: {
                matchLabels: {
                    appClass: "my-deployment",
                },
            },
            template: {
                metadata: {
                    labels: {
                        appClass: "my-deployment",
                    },
                },
                spec: {
                    containers: [
                        {
                            name: "my-deployment",
                            image: "nginx",
                            ports: [
                                {
                                    name: "http",
                                    containerPort: 80,
                                },
                            ],
                        },
                    ],
                },
            },
        },
    });
    const myService = new kubernetes.core.v1.Service("my-service", {
        metadata: {
            labels: {
                appClass: "my-deployment",
            },
        },
        spec: {
            type: "LoadBalancer",
            ports: [
                {
                    port: 80,
                    targetPort: "http",
                },
            ],
            selector: {
                appClass: "my-deployment",
            },
        },
    });
    
    // Export the URL for the load balanced service.
    export const url = myService.status.apply(status => status?.loadBalancer?.ingress[0]?.hostname);
    
    import pulumi
    import pulumi_kubernetes as kubernetes
    
    # Create an NGINX Deployment and load balanced Service.
    my_deployment = kubernetes.apps.v1.Deployment("my-deployment",
        metadata=kubernetes.meta.v1.ObjectMetaArgs(
            labels={
                "appClass": "my-deployment",
            },
        ),
        spec=kubernetes.apps.v1.DeploymentSpecArgs(
            replicas=2,
            selector=kubernetes.meta.v1.LabelSelectorArgs(
                match_labels={
                    "appClass": "my-deployment",
                },
            ),
            template=kubernetes.core.v1.PodTemplateSpecArgs(
                metadata=kubernetes.meta.v1.ObjectMetaArgs(
                    labels={
                        "appClass": "my-deployment",
                    },
                ),
                spec=kubernetes.core.v1.PodSpecArgs(
                    containers=[kubernetes.core.v1.ContainerArgs(
                        name="my-deployment",
                        image="nginx",
                        ports=[kubernetes.core.v1.ContainerPortArgs(
                            name="http",
                            container_port=80,
                        )],
                    )],
                ),
            ),
        ))
    my_service = kubernetes.core.v1.Service("my-service",
        metadata=kubernetes.meta.v1.ObjectMetaArgs(
            labels={
                "appClass": "my-deployment",
            },
        ),
        spec=kubernetes.core.v1.ServiceSpecArgs(
            type="LoadBalancer",
            ports=[kubernetes.core.v1.ServicePortArgs(
                port=80,
                target_port="http",
            )],
            selector={
                "appClass": "my-deployment",
            },
        ))
    
    # Export the URL for the load balanced service.
    pulumi.export("url", my_service.status.load_balancer.ingress[0].hostname)
    
    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 {
    		// Create an NGINX Deployment and load balanced Service.
    		_, err := appsv1.NewDeployment(ctx, "my-deployment", &appsv1.DeploymentArgs{
    			Metadata: &metav1.ObjectMetaArgs{
    				Labels: pulumi.StringMap{
    					"appClass": pulumi.String("my-deployment"),
    				},
    			},
    			Spec: &appsv1.DeploymentSpecArgs{
    				Replicas: pulumi.Int(2),
    				Selector: &metav1.LabelSelectorArgs{
    					MatchLabels: pulumi.StringMap{
    						"appClass": pulumi.String("my-deployment"),
    					},
    				},
    				Template: &corev1.PodTemplateSpecArgs{
    					Metadata: &metav1.ObjectMetaArgs{
    						Labels: pulumi.StringMap{
    							"appClass": pulumi.String("my-deployment"),
    						},
    					},
    					Spec: &corev1.PodSpecArgs{
    						Containers: corev1.ContainerArray{
    							&corev1.ContainerArgs{
    								Name:  pulumi.String("my-deployment"),
    								Image: pulumi.String("nginx"),
    								Ports: corev1.ContainerPortArray{
    									&corev1.ContainerPortArgs{
    										Name:          pulumi.String("http"),
    										ContainerPort: pulumi.Int(80),
    									},
    								},
    							},
    						},
    					},
    				},
    			},
    		})
    		if err != nil {
    			return err
    		}
    		myService, err := corev1.NewService(ctx, "my-service", &corev1.ServiceArgs{
    			Metadata: &metav1.ObjectMetaArgs{
    				Labels: pulumi.StringMap{
    					"appClass": pulumi.String("my-deployment"),
    				},
    			},
    			Spec: &corev1.ServiceSpecArgs{
    				Type: pulumi.String("LoadBalancer"),
    				Ports: corev1.ServicePortArray{
    					&corev1.ServicePortArgs{
    						Port:       pulumi.Int(80),
    						TargetPort: pulumi.Any("http"),
    					},
    				},
    				Selector: pulumi.StringMap{
    					"appClass": pulumi.String("my-deployment"),
    				},
    			},
    		})
    		if err != nil {
    			return err
    		}
    		// Export the URL for the load balanced service.
    		ctx.Export("url", myService.Status.ApplyT(func(status interface{}) (string, error) {
    			s := status.(*corev1.ServiceStatus)
    			if s.LoadBalancer == nil || len(s.LoadBalancer.Ingress) == 0 || s.LoadBalancer.Ingress[0].Hostname == nil {
    				return "", nil
    			}
    			return *s.LoadBalancer.Ingress[0].Hostname, nil
    		}).(pulumi.StringOutput))
    		return nil
    	})
    }
    
    using System.Collections.Generic;
    using Pulumi;
    using Kubernetes = Pulumi.Kubernetes;
    
    return await Deployment.RunAsync(() =>
    {
        // Create an NGINX Deployment and load balanced Service.
        var myDeployment = new Kubernetes.Apps.V1.Deployment("my-deployment", new()
        {
            Metadata = new Kubernetes.Types.Inputs.Meta.V1.ObjectMetaArgs
            {
                Labels =
                {
                    { "appClass", "my-deployment" },
                },
            },
            Spec = new Kubernetes.Types.Inputs.Apps.V1.DeploymentSpecArgs
            {
                Replicas = 2,
                Selector = new Kubernetes.Types.Inputs.Meta.V1.LabelSelectorArgs
                {
                    MatchLabels =
                    {
                        { "appClass", "my-deployment" },
                    },
                },
                Template = new Kubernetes.Types.Inputs.Core.V1.PodTemplateSpecArgs
                {
                    Metadata = new Kubernetes.Types.Inputs.Meta.V1.ObjectMetaArgs
                    {
                        Labels =
                        {
                            { "appClass", "my-deployment" },
                        },
                    },
                    Spec = new Kubernetes.Types.Inputs.Core.V1.PodSpecArgs
                    {
                        Containers = new[]
                        {
                            new Kubernetes.Types.Inputs.Core.V1.ContainerArgs
                            {
                                Name = "my-deployment",
                                Image = "nginx",
                                Ports = new[]
                                {
                                    new Kubernetes.Types.Inputs.Core.V1.ContainerPortArgs
                                    {
                                        Name = "http",
                                        ContainerPortValue = 80,
                                    },
                                },
                            },
                        },
                    },
                },
            },
        });
    
        var myService = new Kubernetes.Core.V1.Service("my-service", new()
        {
            Metadata = new Kubernetes.Types.Inputs.Meta.V1.ObjectMetaArgs
            {
                Labels =
                {
                    { "appClass", "my-deployment" },
                },
            },
            Spec = new Kubernetes.Types.Inputs.Core.V1.ServiceSpecArgs
            {
                Type = "LoadBalancer",
                Ports = new[]
                {
                    new Kubernetes.Types.Inputs.Core.V1.ServicePortArgs
                    {
                        Port = 80,
                        TargetPort = "http",
                    },
                },
                Selector =
                {
                    { "appClass", "my-deployment" },
                },
            },
        });
    
        // Export the URL for the load balanced service.
        return new Dictionary<string, object?>
        {
            ["url"] = myService.Status.Apply(status => status?.LoadBalancer?.Ingress[0]?.Hostname),
        };
    });
    
    package myproject;
    
    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.ServicePortArgs;
    import com.pulumi.kubernetes.core.v1.inputs.ContainerArgs;
    import com.pulumi.kubernetes.core.v1.inputs.ContainerPortArgs;
    import com.pulumi.kubernetes.core.v1.inputs.PodSpecArgs;
    import com.pulumi.kubernetes.core.v1.Service;
    import com.pulumi.kubernetes.core.v1.ServiceArgs;
    import com.pulumi.kubernetes.core.v1.inputs.ServiceSpecArgs;
    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) {
            // Create an NGINX Deployment and load balanced Service.
            var myDeployment = new Deployment("my-deployment", DeploymentArgs.builder()
                .metadata(ObjectMetaArgs.builder()
                    .labels(Map.of("appClass", "my-deployment"))
                    .build())
                .spec(DeploymentSpecArgs.builder()
                    .replicas(2)
                    .selector(LabelSelectorArgs.builder()
                        .matchLabels(Map.of("appClass", "my-deployment"))
                        .build())
                    .template(PodTemplateSpecArgs.builder()
                        .metadata(ObjectMetaArgs.builder()
                            .labels(Map.of("appClass", "my-deployment"))
                            .build())
                        .spec(PodSpecArgs.builder()
                            .containers(ContainerArgs.builder()
                                .name("my-deployment")
                                .image("nginx")
                                .ports(ContainerPortArgs.builder()
                                    .name("http")
                                    .containerPort(80)
                                    .build())
                                .build())
                            .build())
                        .build())
                    .build())
                .build());
    
            var myService = new Service("my-service", ServiceArgs.builder()
                .metadata(ObjectMetaArgs.builder()
                    .labels(Map.of("appClass", "my-deployment"))
                    .build())
                .spec(ServiceSpecArgs.builder()
                    .type("LoadBalancer")
                    .ports(ServicePortArgs.builder()
                        .port(80)
                        .targetPort("http")
                        .build())
                    .selector(Map.of("appClass", "my-deployment"))
                    .build())
                .build());
    
            // Export the URL for the load balanced service.
            ctx.export("url", myService.status().applyValue(status -> {
                return status
                    .flatMap(s -> s.loadBalancer())
                    .map(lb -> lb.ingress())
                    .filter(ingress -> !ingress.isEmpty())
                    .flatMap(ingress -> ingress.get(0).hostname())
                    .orElse("");
            }));
        }
    }
    
    name: aws-k8s-nginx-deploy-yaml
    runtime: yaml
    description: An example that deploys an NGINX service to Kubernetes.
    resources:
      # Deploy an NGINX deployment and load balanced service.
      my-deployment:
        type: kubernetes:apps/v1:Deployment
        properties:
          metadata:
            labels:
              appClass: my-deployment
          spec:
            replicas: 2
            selector:
              matchLabels:
                appClass: my-deployment
            template:
              metadata:
                labels:
                  appClass: my-deployment
              spec:
                containers:
                  - name: my-deployment
                    image: nginx
                    ports:
                      - name: http
                        containerPort: 80
      my-service:
        type: kubernetes:core/v1:Service
        properties:
          metadata:
            labels:
              appClass: my-deployment
          spec:
            type: LoadBalancer
            ports:
              - port: 80
                targetPort: http
            selector:
              appClass: my-deployment
    outputs:
      # Export the URL for the load balanced service.
      url: ${my-service.status.loadBalancer.ingress[0].hostname}
    

    Running pulumi up deploys these Kubernetes objects, providing rich status updates along the way:

    Updating (dev):
    
         Type                           Name               Status
         pulumi:pulumi:Stack            eks-cluster-dev
     +   ├─ kubernetes:core:Service     my-app-svc         created
     +   └─ kubernetes:apps:Deployment  my-app-dep         created
    
    Outputs:
     + url       : "a2861638e011e98a329401e61c-1335818318.us-west-2.elb.amazonaws.com"
    
    Resources:
        + 2 created
    
    Duration: 22s
    

    Deploying existing Kubernetes YAML config to your EKS cluster

    Specifying your Kubernetes object configurations in Pulumi lets you take advantage of programming language features, like variables, loops, conditionals, functions, and classes. It is possible, however, to deploy existing Kubernetes YAML. The two approaches can be mixed, which is useful when converting an existing project.

    The ConfigFile class can be used to deploy a single YAML file, whereas the ConfigGroup class can deploy a collection of files, either from a set of files or in-memory representations.

    For example, suppose you have a directory, yaml/, containing the full YAML for the Kubernetes Guestbook application, perhaps across multiple files. Deploy it into your EKS cluster with the following code and by running pulumi up:

    import * as eks from "@pulumi/eks";
    import * as k8s from "@pulumi/kubernetes";
    
    // Create an EKS cluster.
    const cluster = new eks.Cluster("my-cluster");
    
    // Create resources from standard Kubernetes guestbook YAML example.
    const guestbook = new k8s.yaml.v2.ConfigGroup("guestbook", { files: ["yaml/*.yaml"] }, { provider: cluster.provider });
    
    // Export the cluster's kubeconfig.
    export const kubeconfig = cluster.kubeconfig;
    
    import pulumi
    import pulumi_eks as eks
    import pulumi_kubernetes as kubernetes
    from pulumi_kubernetes.yaml.v2 import ConfigGroup
    
    # Create an EKS cluster.
    cluster = eks.Cluster("my-cluster")
    
    # Create a Kubernetes provider using the new cluster's kubeconfig.
    eks_provider = kubernetes.Provider("eks-provider", kubeconfig=cluster.kubeconfig_json)
    
    # Create resources from standard Kubernetes guestbook YAML example.
    guestbook = ConfigGroup("guestbook",
        files=["yaml/*.yaml"],
        opts=pulumi.ResourceOptions(provider=eks_provider)
    )
    
    # Export the cluster's kubeconfig.
    pulumi.export("kubeconfig", cluster.kubeconfig)
    
    package main
    
    import (
    	"encoding/json"
    
    	"github.com/pulumi/pulumi-eks/sdk/v4/go/eks"
    	k8s "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes"
    	k8syaml "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/yaml/v2"
    	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    )
    
    func main() {
    	pulumi.Run(func(ctx *pulumi.Context) error {
    		// Create an EKS cluster.
    		cluster, err := eks.NewCluster(ctx, "my-cluster", nil)
    		if err != nil {
    			return err
    		}
    
    		// Create a Kubernetes provider using the new cluster's Kubeconfig.
    		prov, err := k8s.NewProvider(ctx, "my-provider", &k8s.ProviderArgs{
    			Kubeconfig: cluster.Kubeconfig.ApplyT(
    				func(config interface{}) (string, error) {
    					b, err := json.Marshal(config)
    					if err != nil {
    						return "", err
    					}
    					return string(b), nil
    				}).(pulumi.StringOutput),
    		})
    		if err != nil {
    			return err
    		}
    
    		// Create resources from standard Kubernetes guestbook YAML example.
    		_, err = k8syaml.NewConfigGroup(ctx, "guestbook", &k8syaml.ConfigGroupArgs{
    			Files: pulumi.StringArray{pulumi.String("yaml/*.yaml")},
    		}, pulumi.Provider(prov))
    		if err != nil {
    			return err
    		}
    
    		// Export the cluster's kubeconfig.
    		ctx.Export("kubeconfig", cluster.Kubeconfig)
    		return nil
    	})
    }
    
    using System.Collections.Generic;
    using K8s = Pulumi.Kubernetes;
    using K8sYaml = Pulumi.Kubernetes.Yaml.V2;
    using Newtonsoft.Json;
    using Pulumi;
    using Pulumi.Eks;
    
    return await Deployment.RunAsync(() =>
    {
        // Create an EKS cluster.
        var cluster = new Cluster("my-cluster");
    
        // Create a Kubernetes provider using the new cluster's Kubeconfig.
        var eksProvider = new K8s.Provider("eksProvider", new K8s.ProviderArgs
        {
            KubeConfig = cluster.Kubeconfig.Apply(JsonConvert.SerializeObject),
        });
    
        // Create resources from standard Kubernetes guestbook YAML.
        var guestbook = new K8sYaml.ConfigGroup("guestbook", new()
        {
            Files = new[] { "yaml/*.yaml" },
        }, new ComponentResourceOptions { Provider = eksProvider });
    
        return new Dictionary<string, object?>
        {
            ["kubeconfig"] = cluster.Kubeconfig,
        };
    });
    
    package myproject;
    
    import com.pulumi.Context;
    import com.pulumi.Pulumi;
    import com.pulumi.core.Output;
    import com.pulumi.eks.Cluster;
    import com.pulumi.kubernetes.Provider;
    import com.pulumi.kubernetes.ProviderArgs;
    import com.pulumi.kubernetes.yaml.v2.ConfigGroup;
    import com.pulumi.kubernetes.yaml.v2.ConfigGroupArgs;
    import com.pulumi.resources.ComponentResourceOptions;
    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 cluster = new Cluster("cluster");
    
            var eksProvider = new Provider("eksProvider", ProviderArgs.builder()
                .kubeconfig(cluster.kubeconfigJson())
                .build());
    
            var guestbook = new ConfigGroup("guestbook", ConfigGroupArgs.builder()
                .files("yaml/*.yaml")
                .build(), ComponentResourceOptions.builder()
                    .provider(eksProvider)
                    .build());
    
            ctx.export("kubeconfig", cluster.kubeconfig());
        }
    }
    
    name: aws-eks-k8s-configgroup-yaml
    runtime: yaml
    description: An example that deploys Kubernetes YAML resources to an EKS cluster.
    resources:
      eks-provider:
        type: pulumi:providers:kubernetes
        properties:
          kubeconfig: ${cluster.kubeconfigJson}
      cluster:
        type: eks:Cluster
      guestbook:
        type: kubernetes:yaml/v2:ConfigGroup
        properties:
          files:
            - "yaml/*.yaml"
        options:
          provider: ${eks-provider}
    outputs:
      kubeconfig: ${cluster.kubeconfig}
    

    The ConfigFile and ConfigGroup classes support transforms via ResourceOptions, which can be used to ‘monkey patch’ Kubernetes configuration on the fly. This can be used to rewrite configuration to include additional services (like Envoy sidecars), inject tags, and so on.

    For example, a transformation like the following can make all services private to a cluster, by changing LoadBalancer specs into ClusterIPs, in addition to placing objects into a desired namespace:

    const guestbook = new k8s.yaml.v2.ConfigGroup("guestbook", { files: ["yaml/*.yaml"] }, { provider: eksProvider, transforms: [ async args => { const props = args.props as any; // Make every service private to the cluster. if (args.type === "kubernetes:core/v1:Service" && props?.spec?.type === "LoadBalancer") { props.spec.type = "ClusterIP"; } // Put every resource in the created namespace. props.metadata = { ...props.metadata, namespace: namespaceName }; return { props, opts: args.opts }; }, ], });
    eks_provider = kubernetes.Provider("eks-provider", kubeconfig=cluster.kubeconfig_json)

    namespace_name = “guestbook”

    def xform(args): props = dict(args.props) # Make every service private to the cluster. if args.type_ == “kubernetes:core/v1:Service”: spec = dict(props.get(“spec”, {})) if spec.get(“type”) == “LoadBalancer”: spec[“type”] = “ClusterIP” props[“spec”] = spec # Put every resource in the created namespace. meta = dict(props.get(“metadata”, {})) meta[“namespace”] = namespace_name props[“metadata”] = meta return pulumi.ResourceTransformResult(props=props, opts=args.opts)

    guestbook = ConfigGroup(“guestbook”, files=[“yaml/*.yaml”], opts=pulumi.ResourceOptions(

    Files: pulumi.StringArray{pulumi.String("yaml/*.yaml")}, }, pulumi.Provider(prov), pulumi.Transforms([]pulumi.ResourceTransform{ func(_ context.Context, args *pulumi.ResourceTransformArgs) *pulumi.ResourceTransformResult { props := args.Props // Make every service private to the cluster. if args.Type == "kubernetes:core/v1:Service" { if spec, ok := props["spec"].(pulumi.Map); ok { if t, ok := spec["type"].(pulumi.String); ok && string(t) == "LoadBalancer" { spec["type"] = pulumi.String("ClusterIP") } } } // Put every resource in the created namespace. if meta, ok := props["metadata"].(pulumi.Map); ok { meta["namespace"] = pulumi.String(namespaceName) } else { props["metadata"] = pulumi.Map{"namespace": pulumi.String(namespaceName)} } return &pulumi.ResourceTransformResult{ Props: props, Opts: args.Opts, } }, })) return err
    Provider = eksProvider, ResourceTransformations = { (args) => { // Make every service private to the cluster. if (args.Resource.GetResourceType() == "kubernetes:core/v1:Service") { dynamic dynArgs = args.Args; dynArgs.Spec = new K8s.Types.Inputs.Core.V1.ServiceSpecArgs { Type = "ClusterIP", }; } return new ResourceTransformationResult(args.Args, args.Options); }, }, }); });
    Transforms are not yet supported for this resource in Java.
    Transforms are not yet supported for this resource in Pulumi YAML.

    Note that transformations can break your applications by changing settings the application or configuration did not expect, so use this capability with care.

    Deploying existing Helm charts to your EKS cluster

    Pulumi can deploy Helm charts through a variety of means. This includes deploying a chart by name from any Helm repository (over the Internet or on-premises), or from a tarball directly.

    For these examples to work, you will need to install Helm.

    This program installs the WordPress chart into your EKS cluster, using the Release resource type:

    import * as pulumi from "@pulumi/pulumi";
    import * as eks from "@pulumi/eks";
    import * as kubernetes from "@pulumi/kubernetes";
    
    const cluster = new eks.Cluster("cluster", {});
    const eksProvider = new kubernetes.Provider("eks-provider", { kubeconfig: cluster.kubeconfigJson });
    const wordpress = new kubernetes.helm.v3.Release("wordpress", {
        repositoryOpts: {
            repo: "https://charts.bitnami.com/bitnami",
        },
        chart: "wordpress",
        values: {
            wordpressBlogName: "My Cool Kubernetes Blog!",
        },
    }, {
        provider: eksProvider,
    });
    export const kubeconfig = cluster.kubeconfig;
    
    import pulumi
    import pulumi_eks as eks
    import pulumi_kubernetes as kubernetes
    
    cluster = eks.Cluster("cluster")
    eks_provider = kubernetes.Provider("eks-provider", kubeconfig=cluster.kubeconfig_json)
    wordpress = kubernetes.helm.v3.Release("wordpress",
        repository_opts=kubernetes.helm.v3.RepositoryOptsArgs(
            repo="https://charts.bitnami.com/bitnami",
        ),
        chart="wordpress",
        values={
            "wordpressBlogName": "My Cool Kubernetes Blog!",
        },
        opts=pulumi.ResourceOptions(provider=eks_provider))
    pulumi.export("kubeconfig", cluster.kubeconfig)
    
    package main
    
    import (
    	"github.com/pulumi/pulumi-eks/sdk/v4/go/eks"
    	"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes"
    	helmv3 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/helm/v3"
    	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    )
    
    func main() {
    	pulumi.Run(func(ctx *pulumi.Context) error {
    		cluster, err := eks.NewCluster(ctx, "cluster", nil)
    		if err != nil {
    			return err
    		}
    		eksProvider, err := kubernetes.NewProvider(ctx, "eks-provider", &kubernetes.ProviderArgs{
    			Kubeconfig: cluster.KubeconfigJson,
    		})
    		if err != nil {
    			return err
    		}
    		_, err = helmv3.NewRelease(ctx, "wordpress", &helmv3.ReleaseArgs{
    			RepositoryOpts: &helmv3.RepositoryOptsArgs{
    				Repo: pulumi.String("https://charts.bitnami.com/bitnami"),
    			},
    			Chart: pulumi.String("wordpress"),
    			Values: pulumi.Map{
    				"wordpressBlogName": pulumi.String("My Cool Kubernetes Blog!"),
    			},
    		}, pulumi.Provider(eksProvider))
    		if err != nil {
    			return err
    		}
    		ctx.Export("kubeconfig", cluster.Kubeconfig)
    		return nil
    	})
    }
    
    using System.Collections.Generic;
    using Pulumi;
    using Eks = Pulumi.Eks;
    using Kubernetes = Pulumi.Kubernetes;
    
    return await Deployment.RunAsync(() =>
    {
        var cluster = new Eks.Cluster("cluster");
    
        var eksProvider = new Kubernetes.Provider("eks-provider", new()
        {
            KubeConfig = cluster.KubeconfigJson,
        });
    
        var wordpress = new Kubernetes.Helm.V3.Release("wordpress", new()
        {
            RepositoryOpts = new Kubernetes.Types.Inputs.Helm.V3.RepositoryOptsArgs
            {
                Repo = "https://charts.bitnami.com/bitnami",
            },
            Chart = "wordpress",
            Values =
            {
                { "wordpressBlogName", "My Cool Kubernetes Blog!" },
            },
        }, new CustomResourceOptions
        {
            Provider = eksProvider,
        });
    
        return new Dictionary<string, object?>
        {
            ["kubeconfig"] = cluster.Kubeconfig,
        };
    });
    
    package myproject;
    
    import com.pulumi.Context;
    import com.pulumi.Pulumi;
    import com.pulumi.core.Output;
    import com.pulumi.eks.Cluster;
    import com.pulumi.kubernetes.Provider;
    import com.pulumi.kubernetes.ProviderArgs;
    import com.pulumi.kubernetes.helm.v3.Release;
    import com.pulumi.kubernetes.helm.v3.ReleaseArgs;
    import com.pulumi.kubernetes.helm.v3.inputs.RepositoryOptsArgs;
    import com.pulumi.resources.CustomResourceOptions;
    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 cluster = new Cluster("cluster");
    
            var eksProvider = new Provider("eksProvider", ProviderArgs.builder()
                .kubeconfig(cluster.kubeconfigJson())
                .build());
    
            var wordpress = new Release("wordpress", ReleaseArgs.builder()
                .repositoryOpts(RepositoryOptsArgs.builder()
                    .repo("https://charts.bitnami.com/bitnami")
                    .build())
                .chart("wordpress")
                .values(Map.of("wordpressBlogName", "My Cool Kubernetes Blog!"))
                .build(), CustomResourceOptions.builder()
                    .provider(eksProvider)
                    .build());
    
            ctx.export("kubeconfig", cluster.kubeconfig());
        }
    }
    
    name: aws-eks-helm-wordpress-yaml
    runtime: yaml
    description: An example that deploys a WordPress Helm chart to an EKS cluster.
    resources:
      eks-provider:
        type: pulumi:providers:kubernetes
        properties:
          kubeconfig: ${cluster.kubeconfigJson}
      cluster:
        type: eks:Cluster
      wordpress:
        type: kubernetes:helm.sh/v3:Release
        properties:
          repositoryOpts:
            repo: https://charts.bitnami.com/bitnami
          chart: wordpress
          values:
            wordpressBlogName: My Cool Kubernetes Blog!
        options:
          provider: ${eks-provider}
    outputs:
      kubeconfig: ${cluster.kubeconfig}
    

    The values array provides the configurable parameters for the chart. If you leave off the version, the latest available chart will be fetched from the repository (including on subsequent updates, which may trigger an upgrade).

    The getResource function on a chart can be used to get an internal resource provisioned by the chart. Sometimes this is needed to discover attributes such as a provisioned load balancer’s address. Be careful when depending on this, however, as it is an implementation detail of the chart and will change as the chart evolves.

    You can also use a tarball fetched from a web URL:

    const helm = new kubernetes.helm.v3.Release("helm", { chart: "https://charts.bitnami.com/bitnami/wordpress-15.2.17.tgz", });
    helm = kubernetes.helm.v3.Release("helm", chart="https://charts.bitnami.com/bitnami/wordpress-15.2.17.tgz")
    func main() { pulumi.Run(func(ctx *pulumi.Context) error { _, err := helmv3.NewRelease(ctx, "helm", &helmv3.ReleaseArgs{ Chart: pulumi.String("https://charts.bitnami.com/bitnami/wordpress-15.2.17.tgz"), }) if err != nil { return err } return nil }) }
    return await Deployment.RunAsync(() => { var helm = new Kubernetes.Helm.V3.Release("helm", new() { Chart = "https://charts.bitnami.com/bitnami/wordpress-15.2.17.tgz", });

    });

    import com.pulumi.kubernetes.helm.v3.ReleaseArgs;

    public class App { public static void main(String[] args) { Pulumi.run(App::stack); }

    public static void stack(Context ctx) {
        var helm = new Release("helm", ReleaseArgs.builder()
            .chart("https://charts.bitnami.com/bitnami/wordpress-15.2.17.tgz")
            .build());
    
    resources: helm: type: kubernetes:helm.sh/v3:Release properties: chart: https://charts.bitnami.com/bitnami/wordpress-15.2.17.tgz

    Using an ECR container image from an EKS Kubernetes deployment

    The Pulumi ECR component enables you to build, publish, and consume private Docker images using Amazon’s Elastic Container Registry (ECR). In the following example, creating an Image resource builds an image from the “./app” directory (relative to the project and containing a Dockerfile), and publishes it to the provisioned ECR repository.

    Note: for more complete examples of building and publishing to any private container registry, including AWS, Azure, Google Cloud, and the Docker Hub, please refer to the article Build and publish container images to any cloud with Infrastructure as Code.

    For example, suppose you have an app/ directory containing a fully Dockerized application (including a Dockerfile), and would like to deploy that as a Deployment and Service running in your EKS cluster. This program accomplishes this with a single pulumi up command:

    import * as pulumi from "@pulumi/pulumi";
    import * as awsx from "@pulumi/awsx";
    import * as eks from "@pulumi/eks";
    import * as kubernetes from "@pulumi/kubernetes";
    
    const appName = "my-app";
    
    const repository = new awsx.ecr.Repository("repository", {
        forceDelete: true,
    });
    
    const image = new awsx.ecr.Image("image", {
        repositoryUrl: repository.url,
        context: "./app",
        platform: "linux/amd64",
    });
    
    const cluster = new eks.Cluster("cluster");
    
    const clusterProvider = new kubernetes.Provider("clusterProvider", {
        kubeconfig: cluster.kubeconfig,
        enableServerSideApply: true,
    });
    
    const deployment = new kubernetes.apps.v1.Deployment(
        "deployment",
        {
            metadata: {
                labels: {
                    appClass: appName,
                },
            },
            spec: {
                replicas: 2,
                selector: {
                    matchLabels: {
                        appClass: appName,
                    },
                },
                template: {
                    metadata: {
                        labels: {
                            appClass: appName,
                        },
                    },
                    spec: {
                        containers: [
                            {
                                name: appName,
                                image: image.imageUri,
                                ports: [
                                    {
                                        name: "http",
                                        containerPort: 80,
                                    },
                                ],
                            },
                        ],
                    },
                },
            },
        },
        {
            provider: clusterProvider,
        },
    );
    
    const service = new kubernetes.core.v1.Service(
        "service",
        {
            metadata: {
                labels: {
                    appClass: appName,
                },
            },
            spec: {
                type: "LoadBalancer",
                selector: {
                    appClass: appName,
                },
                ports: [
                    {
                        port: 80,
                        targetPort: "http",
                    },
                ],
            },
        },
        {
            provider: clusterProvider,
        },
    );
    
    export const url = service.status.apply(status => status?.loadBalancer?.ingress?.[0]?.hostname);
    
    import pulumi
    import pulumi_awsx as awsx
    import pulumi_eks as eks
    import pulumi_kubernetes as kubernetes
    
    app_name = "my-app"
    
    repository = awsx.ecr.Repository(
        "repository",
        awsx.ecr.RepositoryArgs(force_delete=True),
    )
    
    image = awsx.ecr.Image(
        "image",
        awsx.ecr.ImageArgs(
            repository_url=repository.url, context="./app", platform="linux/amd64"
        ),
    )
    
    cluster = eks.Cluster("cluster")
    
    cluster_provider = kubernetes.Provider(
        "clusterProvider", kubeconfig=cluster.kubeconfig, enable_server_side_apply=True
    )
    
    deployment = kubernetes.apps.v1.Deployment(
        "deployment",
        metadata=kubernetes.meta.v1.ObjectMetaArgs(
            labels={
                "appClass": app_name,
            },
        ),
        spec=kubernetes.apps.v1.DeploymentSpecArgs(
            replicas=2,
            selector=kubernetes.meta.v1.LabelSelectorArgs(
                match_labels={
                    "appClass": app_name,
                },
            ),
            template=kubernetes.core.v1.PodTemplateSpecArgs(
                metadata=kubernetes.meta.v1.ObjectMetaArgs(
                    labels={
                        "appClass": app_name,
                    },
                ),
                spec=kubernetes.core.v1.PodSpecArgs(
                    containers=[
                        kubernetes.core.v1.ContainerArgs(
                            name=app_name,
                            image=image.image_uri,
                            ports=[
                                kubernetes.core.v1.ContainerPortArgs(
                                    name="http",
                                    container_port=80,
                                )
                            ],
                        ),
                    ],
                ),
            ),
        ),
        opts=pulumi.ResourceOptions(provider=cluster_provider),
    )
    
    service = kubernetes.core.v1.Service(
        "service",
        metadata=kubernetes.meta.v1.ObjectMetaArgs(
            labels={
                "appClass": app_name,
            },
        ),
        spec=kubernetes.core.v1.ServiceSpecArgs(
            type="LoadBalancer",
            selector={
                "appClass": app_name,
            },
            ports=[
                kubernetes.core.v1.ServicePortArgs(
                    port=80,
                    target_port="http",
                )
            ],
        ),
        opts=pulumi.ResourceOptions(provider=cluster_provider),
    )
    
    pulumi.export("url", service.status.load_balancer.ingress[0].hostname)
    
    package main
    
    import (
    	"github.com/pulumi/pulumi-awsx/sdk/v3/go/awsx/ecr"
    	"github.com/pulumi/pulumi-eks/sdk/v4/go/eks"
    	"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes"
    	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 {
    		appName := "my-app"
    
    		repository, err := ecr.NewRepository(ctx, "repository", &ecr.RepositoryArgs{
    			ForceDelete: pulumi.Bool(true),
    		})
    		if err != nil {
    			return err
    		}
    
    		image, err := ecr.NewImage(ctx, "image", &ecr.ImageArgs{
    			RepositoryUrl: repository.Url,
    			Context:       pulumi.String("./app"),
    			Platform:      pulumi.String("linux/amd64"),
    		})
    		if err != nil {
    			return err
    		}
    
    		cluster, err := eks.NewCluster(ctx, "cluster", nil)
    		if err != nil {
    			return err
    		}
    
    		clusterProvider, err := kubernetes.NewProvider(ctx, "clusterProvider", &kubernetes.ProviderArgs{
    			Kubeconfig:            cluster.KubeconfigJson,
    			EnableServerSideApply: pulumi.Bool(true),
    		})
    		if err != nil {
    			return err
    		}
    
    		_, err = appsv1.NewDeployment(ctx, "deployment", &appsv1.DeploymentArgs{
    			Metadata: &metav1.ObjectMetaArgs{
    				Labels: pulumi.StringMap{
    					"appClass": pulumi.String(appName),
    				},
    			},
    			Spec: &appsv1.DeploymentSpecArgs{
    				Replicas: pulumi.Int(2),
    				Selector: &metav1.LabelSelectorArgs{
    					MatchLabels: pulumi.StringMap{
    						"appClass": pulumi.String(appName),
    					},
    				},
    				Template: &corev1.PodTemplateSpecArgs{
    					Metadata: &metav1.ObjectMetaArgs{
    						Labels: pulumi.StringMap{
    							"appClass": pulumi.String(appName),
    						},
    					},
    					Spec: &corev1.PodSpecArgs{
    						Containers: corev1.ContainerArray{
    							&corev1.ContainerArgs{
    								Name:  pulumi.String(appName),
    								Image: image.ImageUri,
    								Ports: corev1.ContainerPortArray{
    									&corev1.ContainerPortArgs{
    										Name:          pulumi.String("http"),
    										ContainerPort: pulumi.Int(80),
    									},
    								},
    							},
    						},
    					},
    				},
    			},
    		}, pulumi.Provider(clusterProvider))
    		if err != nil {
    			return err
    		}
    
    		service, err := corev1.NewService(ctx, "service", &corev1.ServiceArgs{
    			Metadata: &metav1.ObjectMetaArgs{
    				Labels: pulumi.StringMap{
    					"appClass": pulumi.String(appName),
    				},
    			},
    			Spec: &corev1.ServiceSpecArgs{
    				Type: pulumi.String("LoadBalancer"),
    				Selector: pulumi.StringMap{
    					"appClass": pulumi.String(appName),
    				},
    				Ports: corev1.ServicePortArray{
    					&corev1.ServicePortArgs{
    						Port:       pulumi.Int(80),
    						TargetPort: pulumi.Any("http"),
    					},
    				},
    			},
    		}, pulumi.Provider(clusterProvider))
    		if err != nil {
    			return err
    		}
    
    		hostname := service.Status.LoadBalancer().Ingress().Index(pulumi.Int(0)).Hostname().Elem()
    		ctx.Export("url", pulumi.Sprintf("http://%s", hostname))
    
    		return nil
    	})
    }
    
    using System.Collections.Generic;
    using Pulumi;
    using Awsx = Pulumi.Awsx;
    using Eks = Pulumi.Eks;
    using Kubernetes = Pulumi.Kubernetes;
    
    return await Deployment.RunAsync(() =>
    {
        var appName = "my-app";
    
        var repository = new Awsx.Ecr.Repository("repository", new()
        {
            ForceDelete = true,
        });
    
        var image = new Awsx.Ecr.Image("image", new()
        {
            RepositoryUrl = repository.Url,
            Context = "./app",
            Platform = "linux/amd64",
        });
    
        var cluster = new Eks.Cluster("cluster");
    
        var clusterProvider = new Kubernetes.Provider("clusterProvider", new()
        {
            KubeConfig = cluster.KubeconfigJson,
            EnableServerSideApply = true,
        });
    
        var deployment = new Kubernetes.Apps.V1.Deployment("deployment", new()
        {
            Metadata = new Kubernetes.Types.Inputs.Meta.V1.ObjectMetaArgs
            {
                Labels =
                {
                    { "appClass", appName },
                },
            },
            Spec = new Kubernetes.Types.Inputs.Apps.V1.DeploymentSpecArgs
            {
                Replicas = 2,
                Selector = new Kubernetes.Types.Inputs.Meta.V1.LabelSelectorArgs
                {
                    MatchLabels =
                    {
                        { "appClass", appName },
                    },
                },
                Template = new Kubernetes.Types.Inputs.Core.V1.PodTemplateSpecArgs
                {
                    Metadata = new Kubernetes.Types.Inputs.Meta.V1.ObjectMetaArgs
                    {
                        Labels =
                        {
                            { "appClass", appName },
                        },
                    },
                    Spec = new Kubernetes.Types.Inputs.Core.V1.PodSpecArgs
                    {
                        Containers = new[]
                        {
                            new Kubernetes.Types.Inputs.Core.V1.ContainerArgs
                            {
                                Name = appName,
                                Image = image.ImageUri,
                                Ports = new[]
                                {
                                    new Kubernetes.Types.Inputs.Core.V1.ContainerPortArgs
                                    {
                                        Name = "http",
                                        ContainerPortValue = 80,
                                    },
                                },
                            },
                        },
                    },
                },
            },
        }, new CustomResourceOptions
        {
            Provider = clusterProvider,
        });
    
        var service = new Kubernetes.Core.V1.Service("service", new()
        {
            Metadata = new Kubernetes.Types.Inputs.Meta.V1.ObjectMetaArgs
            {
                Labels =
                {
                    { "appClass", appName },
                },
            },
            Spec = new Kubernetes.Types.Inputs.Core.V1.ServiceSpecArgs
            {
                Type = "LoadBalancer",
                Selector =
                {
                    { "appClass", appName },
                },
                Ports = new[]
                {
                    new Kubernetes.Types.Inputs.Core.V1.ServicePortArgs
                    {
                        Port = 80,
                        TargetPort = "http",
                    },
                },
            },
        }, new CustomResourceOptions
        {
            Provider = clusterProvider,
        });
    
        var hostname = service.Status.Apply(status => status.LoadBalancer.Ingress[0].Hostname);
    
        return new Dictionary<string, object?>
        {
            ["url"] = Output.Format($"http://{hostname}"),
        };
    });
    
    package myproject;
    
    import com.pulumi.Context;
    import com.pulumi.Pulumi;
    import com.pulumi.core.Output;
    import com.pulumi.awsx.ecr.Repository;
    import com.pulumi.awsx.ecr.RepositoryArgs;
    import com.pulumi.awsx.ecr.Image;
    import com.pulumi.awsx.ecr.ImageArgs;
    import com.pulumi.eks.Cluster;
    import com.pulumi.kubernetes.Provider;
    import com.pulumi.kubernetes.ProviderArgs;
    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.ServicePortArgs;
    import com.pulumi.kubernetes.core.v1.inputs.ContainerArgs;
    import com.pulumi.kubernetes.core.v1.inputs.ContainerPortArgs;
    import com.pulumi.kubernetes.core.v1.inputs.PodSpecArgs;
    import com.pulumi.kubernetes.core.v1.Service;
    import com.pulumi.kubernetes.core.v1.ServiceArgs;
    import com.pulumi.kubernetes.core.v1.inputs.ServiceSpecArgs;
    import com.pulumi.resources.CustomResourceOptions;
    import java.util.Map;
    
    public class App {
        public static void main(String[] args) {
            Pulumi.run(App::stack);
        }
    
        public static void stack(Context ctx) {
            final var appName = "my-app";
    
            var repository = new Repository("repository", RepositoryArgs.builder()
                .forceDelete(true)
                .build());
    
            var image = new Image("image", ImageArgs.builder()
                .repositoryUrl(repository.url())
                .context("./app")
                .platform("linux/amd64")
                .build());
    
            var cluster = new Cluster("cluster");
    
            var clusterProvider = new Provider("clusterProvider", ProviderArgs.builder()
                .kubeconfig(cluster.kubeconfigJson())
                .enableServerSideApply(true)
                .build());
    
            var deployment = new Deployment("deployment", DeploymentArgs.builder()
                .metadata(ObjectMetaArgs.builder()
                    .labels(Map.of("appClass", appName))
                    .build())
                .spec(DeploymentSpecArgs.builder()
                    .replicas(2)
                    .selector(LabelSelectorArgs.builder()
                        .matchLabels(Map.of("appClass", appName))
                        .build())
                    .template(PodTemplateSpecArgs.builder()
                        .metadata(ObjectMetaArgs.builder()
                            .labels(Map.of("appClass", appName))
                            .build())
                        .spec(PodSpecArgs.builder()
                            .containers(ContainerArgs.builder()
                                .name(appName)
                                .image(image.imageUri())
                                .ports(ContainerPortArgs.builder()
                                    .name("http")
                                    .containerPort(80)
                                    .build())
                                .build())
                            .build())
                        .build())
                    .build())
                .build(), CustomResourceOptions.builder()
                    .provider(clusterProvider)
                    .build());
    
            var service = new Service("service", ServiceArgs.builder()
                .metadata(ObjectMetaArgs.builder()
                    .labels(Map.of("appClass", appName))
                    .build())
                .spec(ServiceSpecArgs.builder()
                    .type("LoadBalancer")
                    .selector(Map.of("appClass", appName))
                    .ports(ServicePortArgs.builder()
                        .port(80)
                        .targetPort("http")
                        .build())
                    .build())
                .build(), CustomResourceOptions.builder()
                    .provider(clusterProvider)
                    .build());
    
            ctx.export("url", Output.format("http://%s", service.status().applyValue(status -> {
                return status.get().loadBalancer().get().ingress().get(0).hostname().get();
            })));
        }
    }
    
    name: awsx-ecr-eks-deployment-service-yaml
    runtime: yaml
    
    variables:
      appName: my-app
    
    resources:
      repository:
        type: awsx:ecr:Repository
    
      image:
        type: awsx:ecr:Image
        properties:
          repositoryUrl: ${repository.url}
          context: "./app"
          platform: "linux/amd64"
    
      cluster:
        type: eks:Cluster
    
      clusterProvider:
        type: pulumi:providers:kubernetes
        properties:
          kubeconfig: ${cluster.kubeconfigJson}
          enableServerSideApply: true
    
      deployment:
        type: kubernetes:apps/v1:Deployment
        properties:
          metadata:
            labels:
              appClass: ${appName}
          spec:
            replicas: 2
            selector:
              matchLabels:
                appClass: ${appName}
            template:
              metadata:
                labels:
                  appClass: ${appName}
              spec:
                containers:
                  - name: ${appName}
                    image: ${image.imageUri}
                    ports:
                      - name: http
                        containerPort: 80
        options:
          provider: ${clusterProvider}
    
      service:
        type: kubernetes:core/v1:Service
        properties:
          metadata:
            labels:
              appClass: ${appName}
          spec:
            type: LoadBalancer
            selector:
              appClass: ${appName}
            ports:
              - port: 80
                targetPort: http
        options:
          provider: ${clusterProvider}
    
    outputs:
      url: http://${service.status.loadBalancer.ingress[0].hostname}
    

    For more information about ECR, see the Pulumi ECR documentation.

    Additional EKS resources

    For more information about Kubernetes and EKS, see the following:

      The infrastructure as code platform for any cloud.