Deploy GCP VMware Clusters

The gcp:gkeonprem/vMwareCluster:VMwareCluster resource, part of the Pulumi GCP provider, defines a GKE on VMware user cluster: its control plane, networking, load balancing, and integration with vCenter infrastructure. This guide focuses on three capabilities: load balancing configuration (MetalLB, F5, manual), network setup (DHCP vs static IP), and advanced features like Dataplane V2.

VMware clusters depend on a registered admin cluster membership in GKE Hub and reference vCenter resources that must exist separately. The examples are intentionally small. Combine them with your own vCenter infrastructure, node pools, and operational policies.

Deploy a cluster with MetalLB load balancing

Most deployments start with MetalLB, which provides load balancing without external infrastructure by managing IP address pools directly.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const cluster_basic = new gcp.gkeonprem.VMwareCluster("cluster-basic", {
    name: "cluster-basic",
    location: "us-west1",
    adminClusterMembership: "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test",
    description: "test cluster",
    onPremVersion: "1.13.1-gke.35",
    annotations: {},
    networkConfig: {
        serviceAddressCidrBlocks: ["10.96.0.0/12"],
        podAddressCidrBlocks: ["192.168.0.0/16"],
        dhcpIpConfig: {
            enabled: true,
        },
    },
    controlPlaneNode: {
        cpus: 4,
        memory: 8192,
        replicas: 1,
    },
    loadBalancer: {
        vipConfig: {
            controlPlaneVip: "10.251.133.5",
            ingressVip: "10.251.135.19",
        },
        metalLbConfig: {
            addressPools: [
                {
                    pool: "ingress-ip",
                    manualAssign: true,
                    addresses: ["10.251.135.19"],
                    avoidBuggyIps: true,
                },
                {
                    pool: "lb-test-ip",
                    manualAssign: true,
                    addresses: ["10.251.135.19"],
                    avoidBuggyIps: true,
                },
            ],
        },
    },
});
import pulumi
import pulumi_gcp as gcp

cluster_basic = gcp.gkeonprem.VMwareCluster("cluster-basic",
    name="cluster-basic",
    location="us-west1",
    admin_cluster_membership="projects/870316890899/locations/global/memberships/gkeonprem-terraform-test",
    description="test cluster",
    on_prem_version="1.13.1-gke.35",
    annotations={},
    network_config={
        "service_address_cidr_blocks": ["10.96.0.0/12"],
        "pod_address_cidr_blocks": ["192.168.0.0/16"],
        "dhcp_ip_config": {
            "enabled": True,
        },
    },
    control_plane_node={
        "cpus": 4,
        "memory": 8192,
        "replicas": 1,
    },
    load_balancer={
        "vip_config": {
            "control_plane_vip": "10.251.133.5",
            "ingress_vip": "10.251.135.19",
        },
        "metal_lb_config": {
            "address_pools": [
                {
                    "pool": "ingress-ip",
                    "manual_assign": True,
                    "addresses": ["10.251.135.19"],
                    "avoid_buggy_ips": True,
                },
                {
                    "pool": "lb-test-ip",
                    "manual_assign": True,
                    "addresses": ["10.251.135.19"],
                    "avoid_buggy_ips": True,
                },
            ],
        },
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/gkeonprem"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := gkeonprem.NewVMwareCluster(ctx, "cluster-basic", &gkeonprem.VMwareClusterArgs{
			Name:                   pulumi.String("cluster-basic"),
			Location:               pulumi.String("us-west1"),
			AdminClusterMembership: pulumi.String("projects/870316890899/locations/global/memberships/gkeonprem-terraform-test"),
			Description:            pulumi.String("test cluster"),
			OnPremVersion:          pulumi.String("1.13.1-gke.35"),
			Annotations:            pulumi.StringMap{},
			NetworkConfig: &gkeonprem.VMwareClusterNetworkConfigArgs{
				ServiceAddressCidrBlocks: pulumi.StringArray{
					pulumi.String("10.96.0.0/12"),
				},
				PodAddressCidrBlocks: pulumi.StringArray{
					pulumi.String("192.168.0.0/16"),
				},
				DhcpIpConfig: &gkeonprem.VMwareClusterNetworkConfigDhcpIpConfigArgs{
					Enabled: pulumi.Bool(true),
				},
			},
			ControlPlaneNode: &gkeonprem.VMwareClusterControlPlaneNodeArgs{
				Cpus:     pulumi.Int(4),
				Memory:   pulumi.Int(8192),
				Replicas: pulumi.Int(1),
			},
			LoadBalancer: &gkeonprem.VMwareClusterLoadBalancerArgs{
				VipConfig: &gkeonprem.VMwareClusterLoadBalancerVipConfigArgs{
					ControlPlaneVip: pulumi.String("10.251.133.5"),
					IngressVip:      pulumi.String("10.251.135.19"),
				},
				MetalLbConfig: &gkeonprem.VMwareClusterLoadBalancerMetalLbConfigArgs{
					AddressPools: gkeonprem.VMwareClusterLoadBalancerMetalLbConfigAddressPoolArray{
						&gkeonprem.VMwareClusterLoadBalancerMetalLbConfigAddressPoolArgs{
							Pool:         pulumi.String("ingress-ip"),
							ManualAssign: pulumi.Bool(true),
							Addresses: pulumi.StringArray{
								pulumi.String("10.251.135.19"),
							},
							AvoidBuggyIps: pulumi.Bool(true),
						},
						&gkeonprem.VMwareClusterLoadBalancerMetalLbConfigAddressPoolArgs{
							Pool:         pulumi.String("lb-test-ip"),
							ManualAssign: pulumi.Bool(true),
							Addresses: pulumi.StringArray{
								pulumi.String("10.251.135.19"),
							},
							AvoidBuggyIps: pulumi.Bool(true),
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var cluster_basic = new Gcp.GkeOnPrem.VMwareCluster("cluster-basic", new()
    {
        Name = "cluster-basic",
        Location = "us-west1",
        AdminClusterMembership = "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test",
        Description = "test cluster",
        OnPremVersion = "1.13.1-gke.35",
        Annotations = null,
        NetworkConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigArgs
        {
            ServiceAddressCidrBlocks = new[]
            {
                "10.96.0.0/12",
            },
            PodAddressCidrBlocks = new[]
            {
                "192.168.0.0/16",
            },
            DhcpIpConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigDhcpIpConfigArgs
            {
                Enabled = true,
            },
        },
        ControlPlaneNode = new Gcp.GkeOnPrem.Inputs.VMwareClusterControlPlaneNodeArgs
        {
            Cpus = 4,
            Memory = 8192,
            Replicas = 1,
        },
        LoadBalancer = new Gcp.GkeOnPrem.Inputs.VMwareClusterLoadBalancerArgs
        {
            VipConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterLoadBalancerVipConfigArgs
            {
                ControlPlaneVip = "10.251.133.5",
                IngressVip = "10.251.135.19",
            },
            MetalLbConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterLoadBalancerMetalLbConfigArgs
            {
                AddressPools = new[]
                {
                    new Gcp.GkeOnPrem.Inputs.VMwareClusterLoadBalancerMetalLbConfigAddressPoolArgs
                    {
                        Pool = "ingress-ip",
                        ManualAssign = true,
                        Addresses = new[]
                        {
                            "10.251.135.19",
                        },
                        AvoidBuggyIps = true,
                    },
                    new Gcp.GkeOnPrem.Inputs.VMwareClusterLoadBalancerMetalLbConfigAddressPoolArgs
                    {
                        Pool = "lb-test-ip",
                        ManualAssign = true,
                        Addresses = new[]
                        {
                            "10.251.135.19",
                        },
                        AvoidBuggyIps = true,
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.gkeonprem.VMwareCluster;
import com.pulumi.gcp.gkeonprem.VMwareClusterArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterNetworkConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterNetworkConfigDhcpIpConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterControlPlaneNodeArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterLoadBalancerArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterLoadBalancerVipConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterLoadBalancerMetalLbConfigArgs;
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_basic = new VMwareCluster("cluster-basic", VMwareClusterArgs.builder()
            .name("cluster-basic")
            .location("us-west1")
            .adminClusterMembership("projects/870316890899/locations/global/memberships/gkeonprem-terraform-test")
            .description("test cluster")
            .onPremVersion("1.13.1-gke.35")
            .annotations(Map.ofEntries(
            ))
            .networkConfig(VMwareClusterNetworkConfigArgs.builder()
                .serviceAddressCidrBlocks("10.96.0.0/12")
                .podAddressCidrBlocks("192.168.0.0/16")
                .dhcpIpConfig(VMwareClusterNetworkConfigDhcpIpConfigArgs.builder()
                    .enabled(true)
                    .build())
                .build())
            .controlPlaneNode(VMwareClusterControlPlaneNodeArgs.builder()
                .cpus(4)
                .memory(8192)
                .replicas(1)
                .build())
            .loadBalancer(VMwareClusterLoadBalancerArgs.builder()
                .vipConfig(VMwareClusterLoadBalancerVipConfigArgs.builder()
                    .controlPlaneVip("10.251.133.5")
                    .ingressVip("10.251.135.19")
                    .build())
                .metalLbConfig(VMwareClusterLoadBalancerMetalLbConfigArgs.builder()
                    .addressPools(                    
                        VMwareClusterLoadBalancerMetalLbConfigAddressPoolArgs.builder()
                            .pool("ingress-ip")
                            .manualAssign(true)
                            .addresses("10.251.135.19")
                            .avoidBuggyIps(true)
                            .build(),
                        VMwareClusterLoadBalancerMetalLbConfigAddressPoolArgs.builder()
                            .pool("lb-test-ip")
                            .manualAssign(true)
                            .addresses("10.251.135.19")
                            .avoidBuggyIps(true)
                            .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  cluster-basic:
    type: gcp:gkeonprem:VMwareCluster
    properties:
      name: cluster-basic
      location: us-west1
      adminClusterMembership: projects/870316890899/locations/global/memberships/gkeonprem-terraform-test
      description: test cluster
      onPremVersion: 1.13.1-gke.35
      annotations: {}
      networkConfig:
        serviceAddressCidrBlocks:
          - 10.96.0.0/12
        podAddressCidrBlocks:
          - 192.168.0.0/16
        dhcpIpConfig:
          enabled: true
      controlPlaneNode:
        cpus: 4
        memory: 8192
        replicas: 1
      loadBalancer:
        vipConfig:
          controlPlaneVip: 10.251.133.5
          ingressVip: 10.251.135.19
        metalLbConfig:
          addressPools:
            - pool: ingress-ip
              manualAssign: 'true'
              addresses:
                - 10.251.135.19
              avoidBuggyIps: true
            - pool: lb-test-ip
              manualAssign: 'true'
              addresses:
                - 10.251.135.19
              avoidBuggyIps: true

The cluster connects to an admin cluster via adminClusterMembership and runs the specified onPremVersion. The networkConfig enables DHCP for automatic IP assignment, while loadBalancer defines VIPs for the control plane and ingress. MetalLB’s addressPools specify which IPs to use for services, with manualAssign controlling whether addresses are automatically allocated or manually specified.

Configure F5 BIG-IP load balancing with advanced features

Organizations with F5 BIG-IP can integrate their clusters directly for enterprise-grade traffic management.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const cluster_f5lb = new gcp.gkeonprem.VMwareCluster("cluster-f5lb", {
    name: "cluster-f5lb",
    location: "us-west1",
    adminClusterMembership: "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test",
    description: "test cluster",
    onPremVersion: "1.13.1-gke.35",
    annotations: {},
    networkConfig: {
        serviceAddressCidrBlocks: ["10.96.0.0/12"],
        podAddressCidrBlocks: ["192.168.0.0/16"],
        dhcpIpConfig: {
            enabled: true,
        },
        controlPlaneV2Config: {
            controlPlaneIpBlock: {
                ips: [{
                    hostname: "test-hostname",
                    ip: "10.0.0.1",
                }],
                netmask: "10.0.0.1/32",
                gateway: "test-gateway",
            },
        },
        vcenterNetwork: "test-vcenter-network",
    },
    controlPlaneNode: {
        cpus: 4,
        memory: 8192,
        replicas: 1,
        autoResizeConfig: {
            enabled: true,
        },
    },
    loadBalancer: {
        vipConfig: {
            controlPlaneVip: "10.251.133.5",
            ingressVip: "10.251.135.19",
        },
        f5Config: {
            address: "10.0.0.1",
            partition: "test-partition",
            snatPool: "test-snap-pool",
        },
    },
    dataplaneV2: {
        dataplaneV2Enabled: true,
        windowsDataplaneV2Enabled: true,
        advancedNetworking: true,
    },
    vmTrackingEnabled: true,
    enableControlPlaneV2: true,
    disableBundledIngress: true,
    authorization: {
        adminUsers: [{
            username: "testuser@gmail.com",
        }],
    },
    antiAffinityGroups: {
        aagConfigDisabled: true,
    },
    autoRepairConfig: {
        enabled: true,
    },
    storage: {
        vsphereCsiDisabled: true,
    },
});
import pulumi
import pulumi_gcp as gcp

cluster_f5lb = gcp.gkeonprem.VMwareCluster("cluster-f5lb",
    name="cluster-f5lb",
    location="us-west1",
    admin_cluster_membership="projects/870316890899/locations/global/memberships/gkeonprem-terraform-test",
    description="test cluster",
    on_prem_version="1.13.1-gke.35",
    annotations={},
    network_config={
        "service_address_cidr_blocks": ["10.96.0.0/12"],
        "pod_address_cidr_blocks": ["192.168.0.0/16"],
        "dhcp_ip_config": {
            "enabled": True,
        },
        "control_plane_v2_config": {
            "control_plane_ip_block": {
                "ips": [{
                    "hostname": "test-hostname",
                    "ip": "10.0.0.1",
                }],
                "netmask": "10.0.0.1/32",
                "gateway": "test-gateway",
            },
        },
        "vcenter_network": "test-vcenter-network",
    },
    control_plane_node={
        "cpus": 4,
        "memory": 8192,
        "replicas": 1,
        "auto_resize_config": {
            "enabled": True,
        },
    },
    load_balancer={
        "vip_config": {
            "control_plane_vip": "10.251.133.5",
            "ingress_vip": "10.251.135.19",
        },
        "f5_config": {
            "address": "10.0.0.1",
            "partition": "test-partition",
            "snat_pool": "test-snap-pool",
        },
    },
    dataplane_v2={
        "dataplane_v2_enabled": True,
        "windows_dataplane_v2_enabled": True,
        "advanced_networking": True,
    },
    vm_tracking_enabled=True,
    enable_control_plane_v2=True,
    disable_bundled_ingress=True,
    authorization={
        "admin_users": [{
            "username": "testuser@gmail.com",
        }],
    },
    anti_affinity_groups={
        "aag_config_disabled": True,
    },
    auto_repair_config={
        "enabled": True,
    },
    storage={
        "vsphere_csi_disabled": True,
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/gkeonprem"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := gkeonprem.NewVMwareCluster(ctx, "cluster-f5lb", &gkeonprem.VMwareClusterArgs{
			Name:                   pulumi.String("cluster-f5lb"),
			Location:               pulumi.String("us-west1"),
			AdminClusterMembership: pulumi.String("projects/870316890899/locations/global/memberships/gkeonprem-terraform-test"),
			Description:            pulumi.String("test cluster"),
			OnPremVersion:          pulumi.String("1.13.1-gke.35"),
			Annotations:            pulumi.StringMap{},
			NetworkConfig: &gkeonprem.VMwareClusterNetworkConfigArgs{
				ServiceAddressCidrBlocks: pulumi.StringArray{
					pulumi.String("10.96.0.0/12"),
				},
				PodAddressCidrBlocks: pulumi.StringArray{
					pulumi.String("192.168.0.0/16"),
				},
				DhcpIpConfig: &gkeonprem.VMwareClusterNetworkConfigDhcpIpConfigArgs{
					Enabled: pulumi.Bool(true),
				},
				ControlPlaneV2Config: &gkeonprem.VMwareClusterNetworkConfigControlPlaneV2ConfigArgs{
					ControlPlaneIpBlock: &gkeonprem.VMwareClusterNetworkConfigControlPlaneV2ConfigControlPlaneIpBlockArgs{
						Ips: gkeonprem.VMwareClusterNetworkConfigControlPlaneV2ConfigControlPlaneIpBlockIpArray{
							&gkeonprem.VMwareClusterNetworkConfigControlPlaneV2ConfigControlPlaneIpBlockIpArgs{
								Hostname: pulumi.String("test-hostname"),
								Ip:       pulumi.String("10.0.0.1"),
							},
						},
						Netmask: pulumi.String("10.0.0.1/32"),
						Gateway: pulumi.String("test-gateway"),
					},
				},
				VcenterNetwork: pulumi.String("test-vcenter-network"),
			},
			ControlPlaneNode: &gkeonprem.VMwareClusterControlPlaneNodeArgs{
				Cpus:     pulumi.Int(4),
				Memory:   pulumi.Int(8192),
				Replicas: pulumi.Int(1),
				AutoResizeConfig: &gkeonprem.VMwareClusterControlPlaneNodeAutoResizeConfigArgs{
					Enabled: pulumi.Bool(true),
				},
			},
			LoadBalancer: &gkeonprem.VMwareClusterLoadBalancerArgs{
				VipConfig: &gkeonprem.VMwareClusterLoadBalancerVipConfigArgs{
					ControlPlaneVip: pulumi.String("10.251.133.5"),
					IngressVip:      pulumi.String("10.251.135.19"),
				},
				F5Config: &gkeonprem.VMwareClusterLoadBalancerF5ConfigArgs{
					Address:   pulumi.String("10.0.0.1"),
					Partition: pulumi.String("test-partition"),
					SnatPool:  pulumi.String("test-snap-pool"),
				},
			},
			DataplaneV2: &gkeonprem.VMwareClusterDataplaneV2Args{
				DataplaneV2Enabled:        pulumi.Bool(true),
				WindowsDataplaneV2Enabled: pulumi.Bool(true),
				AdvancedNetworking:        pulumi.Bool(true),
			},
			VmTrackingEnabled:     pulumi.Bool(true),
			EnableControlPlaneV2:  pulumi.Bool(true),
			DisableBundledIngress: pulumi.Bool(true),
			Authorization: &gkeonprem.VMwareClusterAuthorizationArgs{
				AdminUsers: gkeonprem.VMwareClusterAuthorizationAdminUserArray{
					&gkeonprem.VMwareClusterAuthorizationAdminUserArgs{
						Username: pulumi.String("testuser@gmail.com"),
					},
				},
			},
			AntiAffinityGroups: &gkeonprem.VMwareClusterAntiAffinityGroupsArgs{
				AagConfigDisabled: pulumi.Bool(true),
			},
			AutoRepairConfig: &gkeonprem.VMwareClusterAutoRepairConfigArgs{
				Enabled: pulumi.Bool(true),
			},
			Storage: &gkeonprem.VMwareClusterStorageArgs{
				VsphereCsiDisabled: pulumi.Bool(true),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var cluster_f5lb = new Gcp.GkeOnPrem.VMwareCluster("cluster-f5lb", new()
    {
        Name = "cluster-f5lb",
        Location = "us-west1",
        AdminClusterMembership = "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test",
        Description = "test cluster",
        OnPremVersion = "1.13.1-gke.35",
        Annotations = null,
        NetworkConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigArgs
        {
            ServiceAddressCidrBlocks = new[]
            {
                "10.96.0.0/12",
            },
            PodAddressCidrBlocks = new[]
            {
                "192.168.0.0/16",
            },
            DhcpIpConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigDhcpIpConfigArgs
            {
                Enabled = true,
            },
            ControlPlaneV2Config = new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigControlPlaneV2ConfigArgs
            {
                ControlPlaneIpBlock = new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigControlPlaneV2ConfigControlPlaneIpBlockArgs
                {
                    Ips = new[]
                    {
                        new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigControlPlaneV2ConfigControlPlaneIpBlockIpArgs
                        {
                            Hostname = "test-hostname",
                            Ip = "10.0.0.1",
                        },
                    },
                    Netmask = "10.0.0.1/32",
                    Gateway = "test-gateway",
                },
            },
            VcenterNetwork = "test-vcenter-network",
        },
        ControlPlaneNode = new Gcp.GkeOnPrem.Inputs.VMwareClusterControlPlaneNodeArgs
        {
            Cpus = 4,
            Memory = 8192,
            Replicas = 1,
            AutoResizeConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterControlPlaneNodeAutoResizeConfigArgs
            {
                Enabled = true,
            },
        },
        LoadBalancer = new Gcp.GkeOnPrem.Inputs.VMwareClusterLoadBalancerArgs
        {
            VipConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterLoadBalancerVipConfigArgs
            {
                ControlPlaneVip = "10.251.133.5",
                IngressVip = "10.251.135.19",
            },
            F5Config = new Gcp.GkeOnPrem.Inputs.VMwareClusterLoadBalancerF5ConfigArgs
            {
                Address = "10.0.0.1",
                Partition = "test-partition",
                SnatPool = "test-snap-pool",
            },
        },
        DataplaneV2 = new Gcp.GkeOnPrem.Inputs.VMwareClusterDataplaneV2Args
        {
            DataplaneV2Enabled = true,
            WindowsDataplaneV2Enabled = true,
            AdvancedNetworking = true,
        },
        VmTrackingEnabled = true,
        EnableControlPlaneV2 = true,
        DisableBundledIngress = true,
        Authorization = new Gcp.GkeOnPrem.Inputs.VMwareClusterAuthorizationArgs
        {
            AdminUsers = new[]
            {
                new Gcp.GkeOnPrem.Inputs.VMwareClusterAuthorizationAdminUserArgs
                {
                    Username = "testuser@gmail.com",
                },
            },
        },
        AntiAffinityGroups = new Gcp.GkeOnPrem.Inputs.VMwareClusterAntiAffinityGroupsArgs
        {
            AagConfigDisabled = true,
        },
        AutoRepairConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterAutoRepairConfigArgs
        {
            Enabled = true,
        },
        Storage = new Gcp.GkeOnPrem.Inputs.VMwareClusterStorageArgs
        {
            VsphereCsiDisabled = true,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.gkeonprem.VMwareCluster;
import com.pulumi.gcp.gkeonprem.VMwareClusterArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterNetworkConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterNetworkConfigDhcpIpConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterNetworkConfigControlPlaneV2ConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterNetworkConfigControlPlaneV2ConfigControlPlaneIpBlockArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterControlPlaneNodeArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterControlPlaneNodeAutoResizeConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterLoadBalancerArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterLoadBalancerVipConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterLoadBalancerF5ConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterDataplaneV2Args;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterAuthorizationArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterAntiAffinityGroupsArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterAutoRepairConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterStorageArgs;
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_f5lb = new VMwareCluster("cluster-f5lb", VMwareClusterArgs.builder()
            .name("cluster-f5lb")
            .location("us-west1")
            .adminClusterMembership("projects/870316890899/locations/global/memberships/gkeonprem-terraform-test")
            .description("test cluster")
            .onPremVersion("1.13.1-gke.35")
            .annotations(Map.ofEntries(
            ))
            .networkConfig(VMwareClusterNetworkConfigArgs.builder()
                .serviceAddressCidrBlocks("10.96.0.0/12")
                .podAddressCidrBlocks("192.168.0.0/16")
                .dhcpIpConfig(VMwareClusterNetworkConfigDhcpIpConfigArgs.builder()
                    .enabled(true)
                    .build())
                .controlPlaneV2Config(VMwareClusterNetworkConfigControlPlaneV2ConfigArgs.builder()
                    .controlPlaneIpBlock(VMwareClusterNetworkConfigControlPlaneV2ConfigControlPlaneIpBlockArgs.builder()
                        .ips(VMwareClusterNetworkConfigControlPlaneV2ConfigControlPlaneIpBlockIpArgs.builder()
                            .hostname("test-hostname")
                            .ip("10.0.0.1")
                            .build())
                        .netmask("10.0.0.1/32")
                        .gateway("test-gateway")
                        .build())
                    .build())
                .vcenterNetwork("test-vcenter-network")
                .build())
            .controlPlaneNode(VMwareClusterControlPlaneNodeArgs.builder()
                .cpus(4)
                .memory(8192)
                .replicas(1)
                .autoResizeConfig(VMwareClusterControlPlaneNodeAutoResizeConfigArgs.builder()
                    .enabled(true)
                    .build())
                .build())
            .loadBalancer(VMwareClusterLoadBalancerArgs.builder()
                .vipConfig(VMwareClusterLoadBalancerVipConfigArgs.builder()
                    .controlPlaneVip("10.251.133.5")
                    .ingressVip("10.251.135.19")
                    .build())
                .f5Config(VMwareClusterLoadBalancerF5ConfigArgs.builder()
                    .address("10.0.0.1")
                    .partition("test-partition")
                    .snatPool("test-snap-pool")
                    .build())
                .build())
            .dataplaneV2(VMwareClusterDataplaneV2Args.builder()
                .dataplaneV2Enabled(true)
                .windowsDataplaneV2Enabled(true)
                .advancedNetworking(true)
                .build())
            .vmTrackingEnabled(true)
            .enableControlPlaneV2(true)
            .disableBundledIngress(true)
            .authorization(VMwareClusterAuthorizationArgs.builder()
                .adminUsers(VMwareClusterAuthorizationAdminUserArgs.builder()
                    .username("testuser@gmail.com")
                    .build())
                .build())
            .antiAffinityGroups(VMwareClusterAntiAffinityGroupsArgs.builder()
                .aagConfigDisabled(true)
                .build())
            .autoRepairConfig(VMwareClusterAutoRepairConfigArgs.builder()
                .enabled(true)
                .build())
            .storage(VMwareClusterStorageArgs.builder()
                .vsphereCsiDisabled(true)
                .build())
            .build());

    }
}
resources:
  cluster-f5lb:
    type: gcp:gkeonprem:VMwareCluster
    properties:
      name: cluster-f5lb
      location: us-west1
      adminClusterMembership: projects/870316890899/locations/global/memberships/gkeonprem-terraform-test
      description: test cluster
      onPremVersion: 1.13.1-gke.35
      annotations: {}
      networkConfig:
        serviceAddressCidrBlocks:
          - 10.96.0.0/12
        podAddressCidrBlocks:
          - 192.168.0.0/16
        dhcpIpConfig:
          enabled: true
        controlPlaneV2Config:
          controlPlaneIpBlock:
            ips:
              - hostname: test-hostname
                ip: 10.0.0.1
            netmask: 10.0.0.1/32
            gateway: test-gateway
        vcenterNetwork: test-vcenter-network
      controlPlaneNode:
        cpus: 4
        memory: 8192
        replicas: 1
        autoResizeConfig:
          enabled: true
      loadBalancer:
        vipConfig:
          controlPlaneVip: 10.251.133.5
          ingressVip: 10.251.135.19
        f5Config:
          address: 10.0.0.1
          partition: test-partition
          snatPool: test-snap-pool
      dataplaneV2:
        dataplaneV2Enabled: true
        windowsDataplaneV2Enabled: true
        advancedNetworking: true
      vmTrackingEnabled: true
      enableControlPlaneV2: true
      disableBundledIngress: true
      authorization:
        adminUsers:
          - username: testuser@gmail.com
      antiAffinityGroups:
        aagConfigDisabled: true
      autoRepairConfig:
        enabled: true
      storage:
        vsphereCsiDisabled: true

The f5Config block points to your F5 device by address and specifies the partition and SNAT pool to use. This example also enables dataplaneV2 for improved networking performance and enableControlPlaneV2 for enhanced control plane capabilities. The controlPlaneV2Config defines static IPs for control plane nodes, while authorization grants cluster admin access to specific users.

Use manual load balancing with static IP configuration

Teams with custom load balancers or specific networking requirements can configure manual load balancing with static IP blocks.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const cluster_manuallb = new gcp.gkeonprem.VMwareCluster("cluster-manuallb", {
    name: "cluster-manuallb",
    skipValidations: [
        "WORKSTATION",
        "CONFIG",
        "DOCKER",
    ],
    location: "us-west1",
    adminClusterMembership: "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test",
    description: "test cluster",
    onPremVersion: "1.13.1-gke.35",
    annotations: {},
    networkConfig: {
        serviceAddressCidrBlocks: ["10.96.0.0/12"],
        podAddressCidrBlocks: ["192.168.0.0/16"],
        hostConfig: {
            dnsServers: ["10.254.41.1"],
            ntpServers: ["216.239.35.8"],
            dnsSearchDomains: ["test-domain"],
        },
        staticIpConfig: {
            ipBlocks: [{
                netmask: "255.255.252.0",
                gateway: "10.251.31.254",
                ips: [
                    {
                        ip: "10.251.30.153",
                        hostname: "test-hostname1",
                    },
                    {
                        ip: "10.251.31.206",
                        hostname: "test-hostname2",
                    },
                    {
                        ip: "10.251.31.193",
                        hostname: "test-hostname3",
                    },
                    {
                        ip: "10.251.30.230",
                        hostname: "test-hostname4",
                    },
                ],
            }],
        },
    },
    controlPlaneNode: {
        cpus: 4,
        memory: 8192,
        replicas: 1,
        autoResizeConfig: {
            enabled: true,
        },
    },
    loadBalancer: {
        vipConfig: {
            controlPlaneVip: "10.251.133.5",
            ingressVip: "10.251.135.19",
        },
        manualLbConfig: {
            ingressHttpNodePort: 30005,
            ingressHttpsNodePort: 30006,
            controlPlaneNodePort: 30007,
            konnectivityServerNodePort: 30008,
        },
    },
    vcenter: {
        resourcePool: "test-resource-pool",
        datastore: "test-datastore",
        datacenter: "test-datacenter",
        cluster: "test-cluster",
        folder: "test-folder",
        caCertData: "test-ca-cert-data",
        storagePolicyName: "test-storage-policy-name",
    },
    dataplaneV2: {
        dataplaneV2Enabled: true,
        windowsDataplaneV2Enabled: true,
        advancedNetworking: true,
    },
    vmTrackingEnabled: true,
    enableControlPlaneV2: true,
    enableAdvancedCluster: true,
    upgradePolicy: {
        controlPlaneOnly: true,
    },
    authorization: {
        adminUsers: [{
            username: "testuser@gmail.com",
        }],
    },
    antiAffinityGroups: {
        aagConfigDisabled: true,
    },
    autoRepairConfig: {
        enabled: true,
    },
});
import pulumi
import pulumi_gcp as gcp

cluster_manuallb = gcp.gkeonprem.VMwareCluster("cluster-manuallb",
    name="cluster-manuallb",
    skip_validations=[
        "WORKSTATION",
        "CONFIG",
        "DOCKER",
    ],
    location="us-west1",
    admin_cluster_membership="projects/870316890899/locations/global/memberships/gkeonprem-terraform-test",
    description="test cluster",
    on_prem_version="1.13.1-gke.35",
    annotations={},
    network_config={
        "service_address_cidr_blocks": ["10.96.0.0/12"],
        "pod_address_cidr_blocks": ["192.168.0.0/16"],
        "host_config": {
            "dns_servers": ["10.254.41.1"],
            "ntp_servers": ["216.239.35.8"],
            "dns_search_domains": ["test-domain"],
        },
        "static_ip_config": {
            "ip_blocks": [{
                "netmask": "255.255.252.0",
                "gateway": "10.251.31.254",
                "ips": [
                    {
                        "ip": "10.251.30.153",
                        "hostname": "test-hostname1",
                    },
                    {
                        "ip": "10.251.31.206",
                        "hostname": "test-hostname2",
                    },
                    {
                        "ip": "10.251.31.193",
                        "hostname": "test-hostname3",
                    },
                    {
                        "ip": "10.251.30.230",
                        "hostname": "test-hostname4",
                    },
                ],
            }],
        },
    },
    control_plane_node={
        "cpus": 4,
        "memory": 8192,
        "replicas": 1,
        "auto_resize_config": {
            "enabled": True,
        },
    },
    load_balancer={
        "vip_config": {
            "control_plane_vip": "10.251.133.5",
            "ingress_vip": "10.251.135.19",
        },
        "manual_lb_config": {
            "ingress_http_node_port": 30005,
            "ingress_https_node_port": 30006,
            "control_plane_node_port": 30007,
            "konnectivity_server_node_port": 30008,
        },
    },
    vcenter={
        "resource_pool": "test-resource-pool",
        "datastore": "test-datastore",
        "datacenter": "test-datacenter",
        "cluster": "test-cluster",
        "folder": "test-folder",
        "ca_cert_data": "test-ca-cert-data",
        "storage_policy_name": "test-storage-policy-name",
    },
    dataplane_v2={
        "dataplane_v2_enabled": True,
        "windows_dataplane_v2_enabled": True,
        "advanced_networking": True,
    },
    vm_tracking_enabled=True,
    enable_control_plane_v2=True,
    enable_advanced_cluster=True,
    upgrade_policy={
        "control_plane_only": True,
    },
    authorization={
        "admin_users": [{
            "username": "testuser@gmail.com",
        }],
    },
    anti_affinity_groups={
        "aag_config_disabled": True,
    },
    auto_repair_config={
        "enabled": True,
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/gkeonprem"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := gkeonprem.NewVMwareCluster(ctx, "cluster-manuallb", &gkeonprem.VMwareClusterArgs{
			Name: pulumi.String("cluster-manuallb"),
			SkipValidations: pulumi.StringArray{
				pulumi.String("WORKSTATION"),
				pulumi.String("CONFIG"),
				pulumi.String("DOCKER"),
			},
			Location:               pulumi.String("us-west1"),
			AdminClusterMembership: pulumi.String("projects/870316890899/locations/global/memberships/gkeonprem-terraform-test"),
			Description:            pulumi.String("test cluster"),
			OnPremVersion:          pulumi.String("1.13.1-gke.35"),
			Annotations:            pulumi.StringMap{},
			NetworkConfig: &gkeonprem.VMwareClusterNetworkConfigArgs{
				ServiceAddressCidrBlocks: pulumi.StringArray{
					pulumi.String("10.96.0.0/12"),
				},
				PodAddressCidrBlocks: pulumi.StringArray{
					pulumi.String("192.168.0.0/16"),
				},
				HostConfig: &gkeonprem.VMwareClusterNetworkConfigHostConfigArgs{
					DnsServers: pulumi.StringArray{
						pulumi.String("10.254.41.1"),
					},
					NtpServers: pulumi.StringArray{
						pulumi.String("216.239.35.8"),
					},
					DnsSearchDomains: pulumi.StringArray{
						pulumi.String("test-domain"),
					},
				},
				StaticIpConfig: &gkeonprem.VMwareClusterNetworkConfigStaticIpConfigArgs{
					IpBlocks: gkeonprem.VMwareClusterNetworkConfigStaticIpConfigIpBlockArray{
						&gkeonprem.VMwareClusterNetworkConfigStaticIpConfigIpBlockArgs{
							Netmask: pulumi.String("255.255.252.0"),
							Gateway: pulumi.String("10.251.31.254"),
							Ips: gkeonprem.VMwareClusterNetworkConfigStaticIpConfigIpBlockIpArray{
								&gkeonprem.VMwareClusterNetworkConfigStaticIpConfigIpBlockIpArgs{
									Ip:       pulumi.String("10.251.30.153"),
									Hostname: pulumi.String("test-hostname1"),
								},
								&gkeonprem.VMwareClusterNetworkConfigStaticIpConfigIpBlockIpArgs{
									Ip:       pulumi.String("10.251.31.206"),
									Hostname: pulumi.String("test-hostname2"),
								},
								&gkeonprem.VMwareClusterNetworkConfigStaticIpConfigIpBlockIpArgs{
									Ip:       pulumi.String("10.251.31.193"),
									Hostname: pulumi.String("test-hostname3"),
								},
								&gkeonprem.VMwareClusterNetworkConfigStaticIpConfigIpBlockIpArgs{
									Ip:       pulumi.String("10.251.30.230"),
									Hostname: pulumi.String("test-hostname4"),
								},
							},
						},
					},
				},
			},
			ControlPlaneNode: &gkeonprem.VMwareClusterControlPlaneNodeArgs{
				Cpus:     pulumi.Int(4),
				Memory:   pulumi.Int(8192),
				Replicas: pulumi.Int(1),
				AutoResizeConfig: &gkeonprem.VMwareClusterControlPlaneNodeAutoResizeConfigArgs{
					Enabled: pulumi.Bool(true),
				},
			},
			LoadBalancer: &gkeonprem.VMwareClusterLoadBalancerArgs{
				VipConfig: &gkeonprem.VMwareClusterLoadBalancerVipConfigArgs{
					ControlPlaneVip: pulumi.String("10.251.133.5"),
					IngressVip:      pulumi.String("10.251.135.19"),
				},
				ManualLbConfig: &gkeonprem.VMwareClusterLoadBalancerManualLbConfigArgs{
					IngressHttpNodePort:        pulumi.Int(30005),
					IngressHttpsNodePort:       pulumi.Int(30006),
					ControlPlaneNodePort:       pulumi.Int(30007),
					KonnectivityServerNodePort: pulumi.Int(30008),
				},
			},
			Vcenter: &gkeonprem.VMwareClusterVcenterArgs{
				ResourcePool:      pulumi.String("test-resource-pool"),
				Datastore:         pulumi.String("test-datastore"),
				Datacenter:        pulumi.String("test-datacenter"),
				Cluster:           pulumi.String("test-cluster"),
				Folder:            pulumi.String("test-folder"),
				CaCertData:        pulumi.String("test-ca-cert-data"),
				StoragePolicyName: pulumi.String("test-storage-policy-name"),
			},
			DataplaneV2: &gkeonprem.VMwareClusterDataplaneV2Args{
				DataplaneV2Enabled:        pulumi.Bool(true),
				WindowsDataplaneV2Enabled: pulumi.Bool(true),
				AdvancedNetworking:        pulumi.Bool(true),
			},
			VmTrackingEnabled:     pulumi.Bool(true),
			EnableControlPlaneV2:  pulumi.Bool(true),
			EnableAdvancedCluster: pulumi.Bool(true),
			UpgradePolicy: &gkeonprem.VMwareClusterUpgradePolicyArgs{
				ControlPlaneOnly: pulumi.Bool(true),
			},
			Authorization: &gkeonprem.VMwareClusterAuthorizationArgs{
				AdminUsers: gkeonprem.VMwareClusterAuthorizationAdminUserArray{
					&gkeonprem.VMwareClusterAuthorizationAdminUserArgs{
						Username: pulumi.String("testuser@gmail.com"),
					},
				},
			},
			AntiAffinityGroups: &gkeonprem.VMwareClusterAntiAffinityGroupsArgs{
				AagConfigDisabled: pulumi.Bool(true),
			},
			AutoRepairConfig: &gkeonprem.VMwareClusterAutoRepairConfigArgs{
				Enabled: pulumi.Bool(true),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var cluster_manuallb = new Gcp.GkeOnPrem.VMwareCluster("cluster-manuallb", new()
    {
        Name = "cluster-manuallb",
        SkipValidations = new[]
        {
            "WORKSTATION",
            "CONFIG",
            "DOCKER",
        },
        Location = "us-west1",
        AdminClusterMembership = "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test",
        Description = "test cluster",
        OnPremVersion = "1.13.1-gke.35",
        Annotations = null,
        NetworkConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigArgs
        {
            ServiceAddressCidrBlocks = new[]
            {
                "10.96.0.0/12",
            },
            PodAddressCidrBlocks = new[]
            {
                "192.168.0.0/16",
            },
            HostConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigHostConfigArgs
            {
                DnsServers = new[]
                {
                    "10.254.41.1",
                },
                NtpServers = new[]
                {
                    "216.239.35.8",
                },
                DnsSearchDomains = new[]
                {
                    "test-domain",
                },
            },
            StaticIpConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigStaticIpConfigArgs
            {
                IpBlocks = new[]
                {
                    new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigStaticIpConfigIpBlockArgs
                    {
                        Netmask = "255.255.252.0",
                        Gateway = "10.251.31.254",
                        Ips = new[]
                        {
                            new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigStaticIpConfigIpBlockIpArgs
                            {
                                Ip = "10.251.30.153",
                                Hostname = "test-hostname1",
                            },
                            new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigStaticIpConfigIpBlockIpArgs
                            {
                                Ip = "10.251.31.206",
                                Hostname = "test-hostname2",
                            },
                            new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigStaticIpConfigIpBlockIpArgs
                            {
                                Ip = "10.251.31.193",
                                Hostname = "test-hostname3",
                            },
                            new Gcp.GkeOnPrem.Inputs.VMwareClusterNetworkConfigStaticIpConfigIpBlockIpArgs
                            {
                                Ip = "10.251.30.230",
                                Hostname = "test-hostname4",
                            },
                        },
                    },
                },
            },
        },
        ControlPlaneNode = new Gcp.GkeOnPrem.Inputs.VMwareClusterControlPlaneNodeArgs
        {
            Cpus = 4,
            Memory = 8192,
            Replicas = 1,
            AutoResizeConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterControlPlaneNodeAutoResizeConfigArgs
            {
                Enabled = true,
            },
        },
        LoadBalancer = new Gcp.GkeOnPrem.Inputs.VMwareClusterLoadBalancerArgs
        {
            VipConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterLoadBalancerVipConfigArgs
            {
                ControlPlaneVip = "10.251.133.5",
                IngressVip = "10.251.135.19",
            },
            ManualLbConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterLoadBalancerManualLbConfigArgs
            {
                IngressHttpNodePort = 30005,
                IngressHttpsNodePort = 30006,
                ControlPlaneNodePort = 30007,
                KonnectivityServerNodePort = 30008,
            },
        },
        Vcenter = new Gcp.GkeOnPrem.Inputs.VMwareClusterVcenterArgs
        {
            ResourcePool = "test-resource-pool",
            Datastore = "test-datastore",
            Datacenter = "test-datacenter",
            Cluster = "test-cluster",
            Folder = "test-folder",
            CaCertData = "test-ca-cert-data",
            StoragePolicyName = "test-storage-policy-name",
        },
        DataplaneV2 = new Gcp.GkeOnPrem.Inputs.VMwareClusterDataplaneV2Args
        {
            DataplaneV2Enabled = true,
            WindowsDataplaneV2Enabled = true,
            AdvancedNetworking = true,
        },
        VmTrackingEnabled = true,
        EnableControlPlaneV2 = true,
        EnableAdvancedCluster = true,
        UpgradePolicy = new Gcp.GkeOnPrem.Inputs.VMwareClusterUpgradePolicyArgs
        {
            ControlPlaneOnly = true,
        },
        Authorization = new Gcp.GkeOnPrem.Inputs.VMwareClusterAuthorizationArgs
        {
            AdminUsers = new[]
            {
                new Gcp.GkeOnPrem.Inputs.VMwareClusterAuthorizationAdminUserArgs
                {
                    Username = "testuser@gmail.com",
                },
            },
        },
        AntiAffinityGroups = new Gcp.GkeOnPrem.Inputs.VMwareClusterAntiAffinityGroupsArgs
        {
            AagConfigDisabled = true,
        },
        AutoRepairConfig = new Gcp.GkeOnPrem.Inputs.VMwareClusterAutoRepairConfigArgs
        {
            Enabled = true,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.gkeonprem.VMwareCluster;
import com.pulumi.gcp.gkeonprem.VMwareClusterArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterNetworkConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterNetworkConfigHostConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterNetworkConfigStaticIpConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterControlPlaneNodeArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterControlPlaneNodeAutoResizeConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterLoadBalancerArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterLoadBalancerVipConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterLoadBalancerManualLbConfigArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterVcenterArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterDataplaneV2Args;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterUpgradePolicyArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterAuthorizationArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterAntiAffinityGroupsArgs;
import com.pulumi.gcp.gkeonprem.inputs.VMwareClusterAutoRepairConfigArgs;
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_manuallb = new VMwareCluster("cluster-manuallb", VMwareClusterArgs.builder()
            .name("cluster-manuallb")
            .skipValidations(            
                "WORKSTATION",
                "CONFIG",
                "DOCKER")
            .location("us-west1")
            .adminClusterMembership("projects/870316890899/locations/global/memberships/gkeonprem-terraform-test")
            .description("test cluster")
            .onPremVersion("1.13.1-gke.35")
            .annotations(Map.ofEntries(
            ))
            .networkConfig(VMwareClusterNetworkConfigArgs.builder()
                .serviceAddressCidrBlocks("10.96.0.0/12")
                .podAddressCidrBlocks("192.168.0.0/16")
                .hostConfig(VMwareClusterNetworkConfigHostConfigArgs.builder()
                    .dnsServers("10.254.41.1")
                    .ntpServers("216.239.35.8")
                    .dnsSearchDomains("test-domain")
                    .build())
                .staticIpConfig(VMwareClusterNetworkConfigStaticIpConfigArgs.builder()
                    .ipBlocks(VMwareClusterNetworkConfigStaticIpConfigIpBlockArgs.builder()
                        .netmask("255.255.252.0")
                        .gateway("10.251.31.254")
                        .ips(                        
                            VMwareClusterNetworkConfigStaticIpConfigIpBlockIpArgs.builder()
                                .ip("10.251.30.153")
                                .hostname("test-hostname1")
                                .build(),
                            VMwareClusterNetworkConfigStaticIpConfigIpBlockIpArgs.builder()
                                .ip("10.251.31.206")
                                .hostname("test-hostname2")
                                .build(),
                            VMwareClusterNetworkConfigStaticIpConfigIpBlockIpArgs.builder()
                                .ip("10.251.31.193")
                                .hostname("test-hostname3")
                                .build(),
                            VMwareClusterNetworkConfigStaticIpConfigIpBlockIpArgs.builder()
                                .ip("10.251.30.230")
                                .hostname("test-hostname4")
                                .build())
                        .build())
                    .build())
                .build())
            .controlPlaneNode(VMwareClusterControlPlaneNodeArgs.builder()
                .cpus(4)
                .memory(8192)
                .replicas(1)
                .autoResizeConfig(VMwareClusterControlPlaneNodeAutoResizeConfigArgs.builder()
                    .enabled(true)
                    .build())
                .build())
            .loadBalancer(VMwareClusterLoadBalancerArgs.builder()
                .vipConfig(VMwareClusterLoadBalancerVipConfigArgs.builder()
                    .controlPlaneVip("10.251.133.5")
                    .ingressVip("10.251.135.19")
                    .build())
                .manualLbConfig(VMwareClusterLoadBalancerManualLbConfigArgs.builder()
                    .ingressHttpNodePort(30005)
                    .ingressHttpsNodePort(30006)
                    .controlPlaneNodePort(30007)
                    .konnectivityServerNodePort(30008)
                    .build())
                .build())
            .vcenter(VMwareClusterVcenterArgs.builder()
                .resourcePool("test-resource-pool")
                .datastore("test-datastore")
                .datacenter("test-datacenter")
                .cluster("test-cluster")
                .folder("test-folder")
                .caCertData("test-ca-cert-data")
                .storagePolicyName("test-storage-policy-name")
                .build())
            .dataplaneV2(VMwareClusterDataplaneV2Args.builder()
                .dataplaneV2Enabled(true)
                .windowsDataplaneV2Enabled(true)
                .advancedNetworking(true)
                .build())
            .vmTrackingEnabled(true)
            .enableControlPlaneV2(true)
            .enableAdvancedCluster(true)
            .upgradePolicy(VMwareClusterUpgradePolicyArgs.builder()
                .controlPlaneOnly(true)
                .build())
            .authorization(VMwareClusterAuthorizationArgs.builder()
                .adminUsers(VMwareClusterAuthorizationAdminUserArgs.builder()
                    .username("testuser@gmail.com")
                    .build())
                .build())
            .antiAffinityGroups(VMwareClusterAntiAffinityGroupsArgs.builder()
                .aagConfigDisabled(true)
                .build())
            .autoRepairConfig(VMwareClusterAutoRepairConfigArgs.builder()
                .enabled(true)
                .build())
            .build());

    }
}
resources:
  cluster-manuallb:
    type: gcp:gkeonprem:VMwareCluster
    properties:
      name: cluster-manuallb
      skipValidations:
        - WORKSTATION
        - CONFIG
        - DOCKER
      location: us-west1
      adminClusterMembership: projects/870316890899/locations/global/memberships/gkeonprem-terraform-test
      description: test cluster
      onPremVersion: 1.13.1-gke.35
      annotations: {}
      networkConfig:
        serviceAddressCidrBlocks:
          - 10.96.0.0/12
        podAddressCidrBlocks:
          - 192.168.0.0/16
        hostConfig:
          dnsServers:
            - 10.254.41.1
          ntpServers:
            - 216.239.35.8
          dnsSearchDomains:
            - test-domain
        staticIpConfig:
          ipBlocks:
            - netmask: 255.255.252.0
              gateway: 10.251.31.254
              ips:
                - ip: 10.251.30.153
                  hostname: test-hostname1
                - ip: 10.251.31.206
                  hostname: test-hostname2
                - ip: 10.251.31.193
                  hostname: test-hostname3
                - ip: 10.251.30.230
                  hostname: test-hostname4
      controlPlaneNode:
        cpus: 4
        memory: 8192
        replicas: 1
        autoResizeConfig:
          enabled: true
      loadBalancer:
        vipConfig:
          controlPlaneVip: 10.251.133.5
          ingressVip: 10.251.135.19
        manualLbConfig:
          ingressHttpNodePort: 30005
          ingressHttpsNodePort: 30006
          controlPlaneNodePort: 30007
          konnectivityServerNodePort: 30008
      vcenter:
        resourcePool: test-resource-pool
        datastore: test-datastore
        datacenter: test-datacenter
        cluster: test-cluster
        folder: test-folder
        caCertData: test-ca-cert-data
        storagePolicyName: test-storage-policy-name
      dataplaneV2:
        dataplaneV2Enabled: true
        windowsDataplaneV2Enabled: true
        advancedNetworking: true
      vmTrackingEnabled: true
      enableControlPlaneV2: true
      enableAdvancedCluster: true
      upgradePolicy:
        controlPlaneOnly: true
      authorization:
        adminUsers:
          - username: testuser@gmail.com
      antiAffinityGroups:
        aagConfigDisabled: true
      autoRepairConfig:
        enabled: true

The manualLbConfig specifies NodePorts for ingress HTTP/HTTPS, control plane, and Konnectivity traffic; your external load balancer routes to these ports. The staticIpConfig defines IP blocks with explicit addresses and hostnames for cluster nodes, while hostConfig sets DNS and NTP servers. The vcenter block specifies where cluster VMs are placed in your vCenter hierarchy. The skipValidations array bypasses preflight checks for workstation, config, and Docker validation.

Beyond these examples

These snippets focus on specific cluster-level features: load balancing options (MetalLB, F5, manual), network configuration (DHCP vs static IP), and advanced cluster features (Dataplane V2, control plane V2). They’re intentionally minimal rather than full Kubernetes deployments.

The examples reference pre-existing infrastructure such as admin cluster membership (GKE Hub registration), vCenter resources (datastores, resource pools, networks), F5 BIG-IP infrastructure (for F5 example), and external load balancer (for manual LB example). They focus on configuring the cluster rather than provisioning the surrounding VMware and networking infrastructure.

To keep things focused, common cluster patterns are omitted, including:

  • Node pool configuration and autoscaling
  • Backup and disaster recovery settings
  • Monitoring and logging integration
  • Certificate management and rotation

These omissions are intentional: the goal is to illustrate how each cluster feature is wired, not provide drop-in production modules. See the VMware Cluster resource reference for all available configuration options.

Let's deploy GCP VMware Clusters

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Limitations
How many control plane replicas can I configure?
Control plane nodes must have either 1 or 3 replicas. Set controlPlaneNode.replicas to 1 for testing or 3 for production high availability.
What properties can't I change after creating the cluster?
The adminClusterMembership, location, name, and project properties are immutable and require cluster recreation to change.
What's the difference between annotations and effectiveAnnotations?
The annotations field only manages annotations in your configuration, while effectiveAnnotations shows all annotations present on the resource, including those added by other clients or services.
Load Balancing
What load balancer options are available?
You can configure MetalLB (metalLbConfig), F5 (f5Config), or manual load balancing (manualLbConfig). Each requires different configuration under the loadBalancer property.
How do I configure MetalLB address pools?
Set loadBalancer.metalLbConfig.addressPools with pool name, addresses, and options like manualAssign and avoidBuggyIps.
Networking
How do I use static IP addresses instead of DHCP?
Configure networkConfig.staticIpConfig with ipBlocks containing netmask, gateway, and IP/hostname pairs. Remove or disable dhcpIpConfig when using static IPs.
What network configuration is required for the cluster?
You must configure networkConfig with serviceAddressCidrBlocks and podAddressCidrBlocks, plus either dhcpIpConfig or staticIpConfig for IP assignment.
Validation & Advanced Features
How do I skip preflight validations during cluster creation?
Use skipValidations with an array of validation types like WORKSTATION, CONFIG, DOCKER, LOAD_BALANCER, or VIPS to bypass specific checks.
What does enableControlPlaneV2 do?
Setting enableControlPlaneV2 to true enables Control Plane V2 features. It defaults to false and appears in advanced cluster configurations.
How do I configure vCenter settings for the cluster?
Set the vcenter property with resourcePool, datastore, datacenter, cluster, folder, and caCertData. These settings are inherited from the admin cluster.

Using a different cloud?

Explore containers guides for other cloud providers: