Deploy GCP VMware Clusters

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

All clusters require an existing admin cluster membership and reference vCenter infrastructure that must be provisioned separately. The examples are intentionally small. Combine them with your own admin cluster, vCenter resources, and network configuration.

Deploy a cluster with MetalLB load balancing

Most VMware user cluster deployments start with MetalLB for load balancing, which provides a straightforward way to expose services without external load balancer hardware.

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 adminClusterMembership connects this user cluster to its admin cluster. The networkConfig defines service and pod CIDR blocks, with dhcpIpConfig enabling automatic IP assignment. The loadBalancer block configures MetalLB with address pools: vipConfig sets control plane and ingress VIPs, while metalLbConfig defines pools with specific IP addresses. The controlPlaneNode specifies CPU, memory, and replica count for control plane nodes.

Configure F5 BIG-IP load balancing with Dataplane V2

Organizations with existing F5 BIG-IP infrastructure can integrate their VMware clusters with F5 for load balancing, often combined with Dataplane V2 for advanced networking features.

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 replaces metalLbConfig, pointing to your F5 BIG-IP address, partition, and SNAT pool. The dataplaneV2 block enables Dataplane V2 features including Windows node support and advanced networking. The controlPlaneV2Config within networkConfig defines static IPs for control plane nodes. Setting enableControlPlaneV2 to true activates the v2 control plane architecture. The authorization block grants cluster admin access to specific users, while antiAffinityGroups and autoRepairConfig control node placement and automatic repairs.

Use static IP allocation with manual load balancing

Environments without DHCP or automated load balancers require static IP configuration and manual load balancer setup, giving teams full control over network addressing.

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

const cluster_manuallb = new gcp.gkeonprem.VMwareCluster("cluster-manuallb", {
    name: "cluster-manuallb",
    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",
    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"),
			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",
        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")
            .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
      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 staticIpConfig block replaces dhcpIpConfig, defining IP blocks with netmask, gateway, and individual IP-to-hostname mappings for cluster nodes. The hostConfig specifies DNS servers, NTP servers, and search domains. The manualLbConfig sets NodePort values for ingress HTTP/HTTPS, control plane, and Konnectivity server traffic; you configure your external load balancer to forward to these ports. The vcenter block defines vCenter resources (resource pool, datastore, datacenter, cluster, folder) where cluster VMs will run. Setting enableAdvancedCluster to true enables advanced cluster features, and upgradePolicy controls whether upgrades affect only the control plane or the entire cluster.

Beyond these examples

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

The examples rely on pre-existing infrastructure such as admin cluster membership (required for all clusters), vCenter resources (resource pools, datastores, datacenters), F5 BIG-IP infrastructure (for F5 example), and DNS and NTP servers (for static IP example). They focus on configuring the cluster rather than provisioning the surrounding VMware and network infrastructure.

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

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

These omissions are intentional: the goal is to illustrate how each cluster feature is wired, not provide drop-in Kubernetes 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 & Setup
What load balancer options are available for VMware clusters?

You can configure three types of load balancers:

  1. MetalLB - Use metalLbConfig with address pools (basic example)
  2. F5 - Use f5Config with address, partition, and SNAT pool (f5lb example)
  3. Manual - Use manualLbConfig with node ports for ingress and control plane (manuallb example)
How do I choose between DHCP and static IP configuration?
Use dhcpIpConfig with enabled: true for dynamic IP assignment, or configure staticIpConfig with ipBlocks containing netmask, gateway, and specific IP addresses with hostnames.
Control Plane & Replicas
How many control plane replicas can I configure?
VMware User Cluster control plane nodes must have either 1 or 3 replicas. No other values are allowed.
Resource Management
What properties can't be changed after cluster creation?
The following properties are immutable: adminClusterMembership, location, name, and project.
Why aren't all my annotations showing in my configuration?
The annotations field is non-authoritative and only manages annotations present in your configuration. Use effectiveAnnotations to see all annotations on the resource.

Using a different cloud?

Explore containers guides for other cloud providers: