The gcp:alloydb/cluster:Cluster resource, part of the Pulumi GCP provider, defines an AlloyDB cluster: the container for database instances, network placement, and backup policies. This guide focuses on four capabilities: network configuration and cluster creation, backup policies, restore operations, and cross-region replication.
AlloyDB clusters require VPC networks and may reference existing backups or primary clusters for restore and replication scenarios. The examples are intentionally small. Combine them with your own VPC infrastructure, instance configurations, and monitoring.
Create a cluster with network configuration
Most deployments begin by creating a cluster in a VPC network, establishing the container for database instances and defining the network boundary for access.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const defaultNetwork = new gcp.compute.Network("default", {name: "alloydb-cluster"});
const _default = new gcp.alloydb.Cluster("default", {
clusterId: "alloydb-cluster",
location: "us-central1",
networkConfig: {
network: defaultNetwork.id,
},
deletionProtection: false,
});
const project = gcp.organizations.getProject({});
import pulumi
import pulumi_gcp as gcp
default_network = gcp.compute.Network("default", name="alloydb-cluster")
default = gcp.alloydb.Cluster("default",
cluster_id="alloydb-cluster",
location="us-central1",
network_config={
"network": default_network.id,
},
deletion_protection=False)
project = gcp.organizations.get_project()
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/alloydb"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
defaultNetwork, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
Name: pulumi.String("alloydb-cluster"),
})
if err != nil {
return err
}
_, err = alloydb.NewCluster(ctx, "default", &alloydb.ClusterArgs{
ClusterId: pulumi.String("alloydb-cluster"),
Location: pulumi.String("us-central1"),
NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
Network: defaultNetwork.ID(),
},
DeletionProtection: pulumi.Bool(false),
})
if err != nil {
return err
}
_, err = organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
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 defaultNetwork = new Gcp.Compute.Network("default", new()
{
Name = "alloydb-cluster",
});
var @default = new Gcp.Alloydb.Cluster("default", new()
{
ClusterId = "alloydb-cluster",
Location = "us-central1",
NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
{
Network = defaultNetwork.Id,
},
DeletionProtection = false,
});
var project = Gcp.Organizations.GetProject.Invoke();
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.alloydb.Cluster;
import com.pulumi.gcp.alloydb.ClusterArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterNetworkConfigArgs;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
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 defaultNetwork = new Network("defaultNetwork", NetworkArgs.builder()
.name("alloydb-cluster")
.build());
var default_ = new Cluster("default", ClusterArgs.builder()
.clusterId("alloydb-cluster")
.location("us-central1")
.networkConfig(ClusterNetworkConfigArgs.builder()
.network(defaultNetwork.id())
.build())
.deletionProtection(false)
.build());
final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
.build());
}
}
resources:
default:
type: gcp:alloydb:Cluster
properties:
clusterId: alloydb-cluster
location: us-central1
networkConfig:
network: ${defaultNetwork.id}
deletionProtection: false
defaultNetwork:
type: gcp:compute:Network
name: default
properties:
name: alloydb-cluster
variables:
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
The clusterId provides a unique identifier within the location. The networkConfig property connects the cluster to your VPC network, enabling private connectivity to database instances. Without additional configuration, the cluster uses default settings for backups and database version.
Configure automated and continuous backups
Production databases require backup strategies that balance recovery objectives with storage costs, using both scheduled backups and continuous backup for point-in-time recovery.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const _default = new gcp.compute.Network("default", {name: "alloydb-cluster-full"});
const full = new gcp.alloydb.Cluster("full", {
clusterId: "alloydb-cluster-full",
location: "us-central1",
networkConfig: {
network: _default.id,
},
databaseVersion: "POSTGRES_15",
initialUser: {
user: "alloydb-cluster-full",
password: "alloydb-cluster-full",
},
continuousBackupConfig: {
enabled: true,
recoveryWindowDays: 14,
},
automatedBackupPolicy: {
location: "us-central1",
backupWindow: "1800s",
enabled: true,
weeklySchedule: {
daysOfWeeks: ["MONDAY"],
startTimes: [{
hours: 23,
minutes: 0,
seconds: 0,
nanos: 0,
}],
},
quantityBasedRetention: {
count: 1,
},
labels: {
test: "alloydb-cluster-full",
},
},
labels: {
test: "alloydb-cluster-full",
},
deletionProtection: false,
});
const project = gcp.organizations.getProject({});
import pulumi
import pulumi_gcp as gcp
default = gcp.compute.Network("default", name="alloydb-cluster-full")
full = gcp.alloydb.Cluster("full",
cluster_id="alloydb-cluster-full",
location="us-central1",
network_config={
"network": default.id,
},
database_version="POSTGRES_15",
initial_user={
"user": "alloydb-cluster-full",
"password": "alloydb-cluster-full",
},
continuous_backup_config={
"enabled": True,
"recovery_window_days": 14,
},
automated_backup_policy={
"location": "us-central1",
"backup_window": "1800s",
"enabled": True,
"weekly_schedule": {
"days_of_weeks": ["MONDAY"],
"start_times": [{
"hours": 23,
"minutes": 0,
"seconds": 0,
"nanos": 0,
}],
},
"quantity_based_retention": {
"count": 1,
},
"labels": {
"test": "alloydb-cluster-full",
},
},
labels={
"test": "alloydb-cluster-full",
},
deletion_protection=False)
project = gcp.organizations.get_project()
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/alloydb"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_default, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
Name: pulumi.String("alloydb-cluster-full"),
})
if err != nil {
return err
}
_, err = alloydb.NewCluster(ctx, "full", &alloydb.ClusterArgs{
ClusterId: pulumi.String("alloydb-cluster-full"),
Location: pulumi.String("us-central1"),
NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
Network: _default.ID(),
},
DatabaseVersion: pulumi.String("POSTGRES_15"),
InitialUser: &alloydb.ClusterInitialUserArgs{
User: pulumi.String("alloydb-cluster-full"),
Password: pulumi.String("alloydb-cluster-full"),
},
ContinuousBackupConfig: &alloydb.ClusterContinuousBackupConfigArgs{
Enabled: pulumi.Bool(true),
RecoveryWindowDays: pulumi.Int(14),
},
AutomatedBackupPolicy: &alloydb.ClusterAutomatedBackupPolicyArgs{
Location: pulumi.String("us-central1"),
BackupWindow: pulumi.String("1800s"),
Enabled: pulumi.Bool(true),
WeeklySchedule: &alloydb.ClusterAutomatedBackupPolicyWeeklyScheduleArgs{
DaysOfWeeks: pulumi.StringArray{
pulumi.String("MONDAY"),
},
StartTimes: alloydb.ClusterAutomatedBackupPolicyWeeklyScheduleStartTimeArray{
&alloydb.ClusterAutomatedBackupPolicyWeeklyScheduleStartTimeArgs{
Hours: pulumi.Int(23),
Minutes: pulumi.Int(0),
Seconds: pulumi.Int(0),
Nanos: pulumi.Int(0),
},
},
},
QuantityBasedRetention: &alloydb.ClusterAutomatedBackupPolicyQuantityBasedRetentionArgs{
Count: pulumi.Int(1),
},
Labels: pulumi.StringMap{
"test": pulumi.String("alloydb-cluster-full"),
},
},
Labels: pulumi.StringMap{
"test": pulumi.String("alloydb-cluster-full"),
},
DeletionProtection: pulumi.Bool(false),
})
if err != nil {
return err
}
_, err = organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
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 @default = new Gcp.Compute.Network("default", new()
{
Name = "alloydb-cluster-full",
});
var full = new Gcp.Alloydb.Cluster("full", new()
{
ClusterId = "alloydb-cluster-full",
Location = "us-central1",
NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
{
Network = @default.Id,
},
DatabaseVersion = "POSTGRES_15",
InitialUser = new Gcp.Alloydb.Inputs.ClusterInitialUserArgs
{
User = "alloydb-cluster-full",
Password = "alloydb-cluster-full",
},
ContinuousBackupConfig = new Gcp.Alloydb.Inputs.ClusterContinuousBackupConfigArgs
{
Enabled = true,
RecoveryWindowDays = 14,
},
AutomatedBackupPolicy = new Gcp.Alloydb.Inputs.ClusterAutomatedBackupPolicyArgs
{
Location = "us-central1",
BackupWindow = "1800s",
Enabled = true,
WeeklySchedule = new Gcp.Alloydb.Inputs.ClusterAutomatedBackupPolicyWeeklyScheduleArgs
{
DaysOfWeeks = new[]
{
"MONDAY",
},
StartTimes = new[]
{
new Gcp.Alloydb.Inputs.ClusterAutomatedBackupPolicyWeeklyScheduleStartTimeArgs
{
Hours = 23,
Minutes = 0,
Seconds = 0,
Nanos = 0,
},
},
},
QuantityBasedRetention = new Gcp.Alloydb.Inputs.ClusterAutomatedBackupPolicyQuantityBasedRetentionArgs
{
Count = 1,
},
Labels =
{
{ "test", "alloydb-cluster-full" },
},
},
Labels =
{
{ "test", "alloydb-cluster-full" },
},
DeletionProtection = false,
});
var project = Gcp.Organizations.GetProject.Invoke();
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.alloydb.Cluster;
import com.pulumi.gcp.alloydb.ClusterArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterNetworkConfigArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterInitialUserArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterContinuousBackupConfigArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterAutomatedBackupPolicyArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterAutomatedBackupPolicyWeeklyScheduleArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterAutomatedBackupPolicyQuantityBasedRetentionArgs;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
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 default_ = new Network("default", NetworkArgs.builder()
.name("alloydb-cluster-full")
.build());
var full = new Cluster("full", ClusterArgs.builder()
.clusterId("alloydb-cluster-full")
.location("us-central1")
.networkConfig(ClusterNetworkConfigArgs.builder()
.network(default_.id())
.build())
.databaseVersion("POSTGRES_15")
.initialUser(ClusterInitialUserArgs.builder()
.user("alloydb-cluster-full")
.password("alloydb-cluster-full")
.build())
.continuousBackupConfig(ClusterContinuousBackupConfigArgs.builder()
.enabled(true)
.recoveryWindowDays(14)
.build())
.automatedBackupPolicy(ClusterAutomatedBackupPolicyArgs.builder()
.location("us-central1")
.backupWindow("1800s")
.enabled(true)
.weeklySchedule(ClusterAutomatedBackupPolicyWeeklyScheduleArgs.builder()
.daysOfWeeks("MONDAY")
.startTimes(ClusterAutomatedBackupPolicyWeeklyScheduleStartTimeArgs.builder()
.hours(23)
.minutes(0)
.seconds(0)
.nanos(0)
.build())
.build())
.quantityBasedRetention(ClusterAutomatedBackupPolicyQuantityBasedRetentionArgs.builder()
.count(1)
.build())
.labels(Map.of("test", "alloydb-cluster-full"))
.build())
.labels(Map.of("test", "alloydb-cluster-full"))
.deletionProtection(false)
.build());
final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
.build());
}
}
resources:
full:
type: gcp:alloydb:Cluster
properties:
clusterId: alloydb-cluster-full
location: us-central1
networkConfig:
network: ${default.id}
databaseVersion: POSTGRES_15
initialUser:
user: alloydb-cluster-full
password: alloydb-cluster-full
continuousBackupConfig:
enabled: true
recoveryWindowDays: 14
automatedBackupPolicy:
location: us-central1
backupWindow: 1800s
enabled: true
weeklySchedule:
daysOfWeeks:
- MONDAY
startTimes:
- hours: 23
minutes: 0
seconds: 0
nanos: 0
quantityBasedRetention:
count: 1
labels:
test: alloydb-cluster-full
labels:
test: alloydb-cluster-full
deletionProtection: false
default:
type: gcp:compute:Network
properties:
name: alloydb-cluster-full
variables:
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
The automatedBackupPolicy defines scheduled backups with weeklySchedule controlling when backups run and quantityBasedRetention setting how many to keep. The continuousBackupConfig enables point-in-time recovery with recoveryWindowDays controlling how far back you can restore. Together, these provide both scheduled recovery points and fine-grained timestamp recovery.
Set database version and initial user credentials
When provisioning a new cluster, you specify the PostgreSQL version and optionally create an initial database user.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const _default = gcp.compute.getNetwork({
name: "alloydb-network",
});
const defaultCluster = new gcp.alloydb.Cluster("default", {
clusterId: "alloydb-cluster",
location: "us-central1",
networkConfig: {
network: _default.then(_default => _default.id),
},
databaseVersion: "POSTGRES_14",
initialUser: {
password: "alloydb-cluster",
},
deletionProtection: false,
});
const defaultInstance = new gcp.alloydb.Instance("default", {
cluster: defaultCluster.name,
instanceId: "alloydb-instance",
instanceType: "PRIMARY",
machineConfig: {
cpuCount: 2,
},
});
import pulumi
import pulumi_gcp as gcp
default = gcp.compute.get_network(name="alloydb-network")
default_cluster = gcp.alloydb.Cluster("default",
cluster_id="alloydb-cluster",
location="us-central1",
network_config={
"network": default.id,
},
database_version="POSTGRES_14",
initial_user={
"password": "alloydb-cluster",
},
deletion_protection=False)
default_instance = gcp.alloydb.Instance("default",
cluster=default_cluster.name,
instance_id="alloydb-instance",
instance_type="PRIMARY",
machine_config={
"cpu_count": 2,
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/alloydb"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_default, err := compute.LookupNetwork(ctx, &compute.LookupNetworkArgs{
Name: "alloydb-network",
}, nil)
if err != nil {
return err
}
defaultCluster, err := alloydb.NewCluster(ctx, "default", &alloydb.ClusterArgs{
ClusterId: pulumi.String("alloydb-cluster"),
Location: pulumi.String("us-central1"),
NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
Network: pulumi.String(_default.Id),
},
DatabaseVersion: pulumi.String("POSTGRES_14"),
InitialUser: &alloydb.ClusterInitialUserArgs{
Password: pulumi.String("alloydb-cluster"),
},
DeletionProtection: pulumi.Bool(false),
})
if err != nil {
return err
}
_, err = alloydb.NewInstance(ctx, "default", &alloydb.InstanceArgs{
Cluster: defaultCluster.Name,
InstanceId: pulumi.String("alloydb-instance"),
InstanceType: pulumi.String("PRIMARY"),
MachineConfig: &alloydb.InstanceMachineConfigArgs{
CpuCount: pulumi.Int(2),
},
})
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 @default = Gcp.Compute.GetNetwork.Invoke(new()
{
Name = "alloydb-network",
});
var defaultCluster = new Gcp.Alloydb.Cluster("default", new()
{
ClusterId = "alloydb-cluster",
Location = "us-central1",
NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
{
Network = @default.Apply(@default => @default.Apply(getNetworkResult => getNetworkResult.Id)),
},
DatabaseVersion = "POSTGRES_14",
InitialUser = new Gcp.Alloydb.Inputs.ClusterInitialUserArgs
{
Password = "alloydb-cluster",
},
DeletionProtection = false,
});
var defaultInstance = new Gcp.Alloydb.Instance("default", new()
{
Cluster = defaultCluster.Name,
InstanceId = "alloydb-instance",
InstanceType = "PRIMARY",
MachineConfig = new Gcp.Alloydb.Inputs.InstanceMachineConfigArgs
{
CpuCount = 2,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.ComputeFunctions;
import com.pulumi.gcp.compute.inputs.GetNetworkArgs;
import com.pulumi.gcp.alloydb.Cluster;
import com.pulumi.gcp.alloydb.ClusterArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterNetworkConfigArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterInitialUserArgs;
import com.pulumi.gcp.alloydb.Instance;
import com.pulumi.gcp.alloydb.InstanceArgs;
import com.pulumi.gcp.alloydb.inputs.InstanceMachineConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var default = ComputeFunctions.getNetwork(GetNetworkArgs.builder()
.name("alloydb-network")
.build());
var defaultCluster = new Cluster("defaultCluster", ClusterArgs.builder()
.clusterId("alloydb-cluster")
.location("us-central1")
.networkConfig(ClusterNetworkConfigArgs.builder()
.network(default_.id())
.build())
.databaseVersion("POSTGRES_14")
.initialUser(ClusterInitialUserArgs.builder()
.password("alloydb-cluster")
.build())
.deletionProtection(false)
.build());
var defaultInstance = new Instance("defaultInstance", InstanceArgs.builder()
.cluster(defaultCluster.name())
.instanceId("alloydb-instance")
.instanceType("PRIMARY")
.machineConfig(InstanceMachineConfigArgs.builder()
.cpuCount(2)
.build())
.build());
}
}
resources:
defaultInstance:
type: gcp:alloydb:Instance
name: default
properties:
cluster: ${defaultCluster.name}
instanceId: alloydb-instance
instanceType: PRIMARY
machineConfig:
cpuCount: 2
defaultCluster:
type: gcp:alloydb:Cluster
name: default
properties:
clusterId: alloydb-cluster
location: us-central1
networkConfig:
network: ${default.id}
databaseVersion: POSTGRES_14
initialUser:
password: alloydb-cluster
deletionProtection: false
variables:
default:
fn::invoke:
function: gcp:compute:getNetwork
arguments:
name: alloydb-network
The databaseVersion property locks the major PostgreSQL version at creation time. Changing this field to a higher version triggers an irreversible upgrade. The initialUser block creates a database user with the specified password. Note that the password is stored in Pulumi state; consider using secrets management for production deployments.
Restore from backup or point-in-time
Disaster recovery scenarios require creating new clusters from existing backups or restoring to a specific timestamp using continuous backup data.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const _default = gcp.compute.getNetwork({
name: "alloydb-network",
});
const source = new gcp.alloydb.Cluster("source", {
clusterId: "alloydb-source-cluster",
location: "us-central1",
network: _default.then(_default => _default.id),
initialUser: {
password: "alloydb-source-cluster",
},
deletionProtection: false,
});
const privateIpAlloc = new gcp.compute.GlobalAddress("private_ip_alloc", {
name: "alloydb-source-cluster",
addressType: "INTERNAL",
purpose: "VPC_PEERING",
prefixLength: 16,
network: _default.then(_default => _default.id),
});
const vpcConnection = new gcp.servicenetworking.Connection("vpc_connection", {
network: _default.then(_default => _default.id),
service: "servicenetworking.googleapis.com",
reservedPeeringRanges: [privateIpAlloc.name],
});
const sourceInstance = new gcp.alloydb.Instance("source", {
cluster: source.name,
instanceId: "alloydb-instance",
instanceType: "PRIMARY",
machineConfig: {
cpuCount: 2,
},
}, {
dependsOn: [vpcConnection],
});
const sourceBackup = new gcp.alloydb.Backup("source", {
backupId: "alloydb-backup",
location: "us-central1",
clusterName: source.name,
}, {
dependsOn: [sourceInstance],
});
const restoredFromBackup = new gcp.alloydb.Cluster("restored_from_backup", {
clusterId: "alloydb-backup-restored",
location: "us-central1",
networkConfig: {
network: _default.then(_default => _default.id),
},
restoreBackupSource: {
backupName: sourceBackup.name,
},
deletionProtection: false,
});
const restoredViaPitr = new gcp.alloydb.Cluster("restored_via_pitr", {
clusterId: "alloydb-pitr-restored",
location: "us-central1",
networkConfig: {
network: _default.then(_default => _default.id),
},
restoreContinuousBackupSource: {
cluster: source.name,
pointInTime: "2023-08-03T19:19:00.094Z",
},
deletionProtection: false,
});
const project = gcp.organizations.getProject({});
import pulumi
import pulumi_gcp as gcp
default = gcp.compute.get_network(name="alloydb-network")
source = gcp.alloydb.Cluster("source",
cluster_id="alloydb-source-cluster",
location="us-central1",
network=default.id,
initial_user={
"password": "alloydb-source-cluster",
},
deletion_protection=False)
private_ip_alloc = gcp.compute.GlobalAddress("private_ip_alloc",
name="alloydb-source-cluster",
address_type="INTERNAL",
purpose="VPC_PEERING",
prefix_length=16,
network=default.id)
vpc_connection = gcp.servicenetworking.Connection("vpc_connection",
network=default.id,
service="servicenetworking.googleapis.com",
reserved_peering_ranges=[private_ip_alloc.name])
source_instance = gcp.alloydb.Instance("source",
cluster=source.name,
instance_id="alloydb-instance",
instance_type="PRIMARY",
machine_config={
"cpu_count": 2,
},
opts = pulumi.ResourceOptions(depends_on=[vpc_connection]))
source_backup = gcp.alloydb.Backup("source",
backup_id="alloydb-backup",
location="us-central1",
cluster_name=source.name,
opts = pulumi.ResourceOptions(depends_on=[source_instance]))
restored_from_backup = gcp.alloydb.Cluster("restored_from_backup",
cluster_id="alloydb-backup-restored",
location="us-central1",
network_config={
"network": default.id,
},
restore_backup_source={
"backup_name": source_backup.name,
},
deletion_protection=False)
restored_via_pitr = gcp.alloydb.Cluster("restored_via_pitr",
cluster_id="alloydb-pitr-restored",
location="us-central1",
network_config={
"network": default.id,
},
restore_continuous_backup_source={
"cluster": source.name,
"point_in_time": "2023-08-03T19:19:00.094Z",
},
deletion_protection=False)
project = gcp.organizations.get_project()
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/alloydb"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/servicenetworking"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_default, err := compute.LookupNetwork(ctx, &compute.LookupNetworkArgs{
Name: "alloydb-network",
}, nil)
if err != nil {
return err
}
source, err := alloydb.NewCluster(ctx, "source", &alloydb.ClusterArgs{
ClusterId: pulumi.String("alloydb-source-cluster"),
Location: pulumi.String("us-central1"),
Network: _default.Id,
InitialUser: &alloydb.ClusterInitialUserArgs{
Password: pulumi.String("alloydb-source-cluster"),
},
DeletionProtection: pulumi.Bool(false),
})
if err != nil {
return err
}
privateIpAlloc, err := compute.NewGlobalAddress(ctx, "private_ip_alloc", &compute.GlobalAddressArgs{
Name: pulumi.String("alloydb-source-cluster"),
AddressType: pulumi.String("INTERNAL"),
Purpose: pulumi.String("VPC_PEERING"),
PrefixLength: pulumi.Int(16),
Network: pulumi.String(_default.Id),
})
if err != nil {
return err
}
vpcConnection, err := servicenetworking.NewConnection(ctx, "vpc_connection", &servicenetworking.ConnectionArgs{
Network: pulumi.String(_default.Id),
Service: pulumi.String("servicenetworking.googleapis.com"),
ReservedPeeringRanges: pulumi.StringArray{
privateIpAlloc.Name,
},
})
if err != nil {
return err
}
sourceInstance, err := alloydb.NewInstance(ctx, "source", &alloydb.InstanceArgs{
Cluster: source.Name,
InstanceId: pulumi.String("alloydb-instance"),
InstanceType: pulumi.String("PRIMARY"),
MachineConfig: &alloydb.InstanceMachineConfigArgs{
CpuCount: pulumi.Int(2),
},
}, pulumi.DependsOn([]pulumi.Resource{
vpcConnection,
}))
if err != nil {
return err
}
sourceBackup, err := alloydb.NewBackup(ctx, "source", &alloydb.BackupArgs{
BackupId: pulumi.String("alloydb-backup"),
Location: pulumi.String("us-central1"),
ClusterName: source.Name,
}, pulumi.DependsOn([]pulumi.Resource{
sourceInstance,
}))
if err != nil {
return err
}
_, err = alloydb.NewCluster(ctx, "restored_from_backup", &alloydb.ClusterArgs{
ClusterId: pulumi.String("alloydb-backup-restored"),
Location: pulumi.String("us-central1"),
NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
Network: pulumi.String(_default.Id),
},
RestoreBackupSource: &alloydb.ClusterRestoreBackupSourceArgs{
BackupName: sourceBackup.Name,
},
DeletionProtection: pulumi.Bool(false),
})
if err != nil {
return err
}
_, err = alloydb.NewCluster(ctx, "restored_via_pitr", &alloydb.ClusterArgs{
ClusterId: pulumi.String("alloydb-pitr-restored"),
Location: pulumi.String("us-central1"),
NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
Network: pulumi.String(_default.Id),
},
RestoreContinuousBackupSource: &alloydb.ClusterRestoreContinuousBackupSourceArgs{
Cluster: source.Name,
PointInTime: pulumi.String("2023-08-03T19:19:00.094Z"),
},
DeletionProtection: pulumi.Bool(false),
})
if err != nil {
return err
}
_, err = organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
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 @default = Gcp.Compute.GetNetwork.Invoke(new()
{
Name = "alloydb-network",
});
var source = new Gcp.Alloydb.Cluster("source", new()
{
ClusterId = "alloydb-source-cluster",
Location = "us-central1",
Network = @default.Apply(@default => @default.Apply(getNetworkResult => getNetworkResult.Id)),
InitialUser = new Gcp.Alloydb.Inputs.ClusterInitialUserArgs
{
Password = "alloydb-source-cluster",
},
DeletionProtection = false,
});
var privateIpAlloc = new Gcp.Compute.GlobalAddress("private_ip_alloc", new()
{
Name = "alloydb-source-cluster",
AddressType = "INTERNAL",
Purpose = "VPC_PEERING",
PrefixLength = 16,
Network = @default.Apply(@default => @default.Apply(getNetworkResult => getNetworkResult.Id)),
});
var vpcConnection = new Gcp.ServiceNetworking.Connection("vpc_connection", new()
{
Network = @default.Apply(@default => @default.Apply(getNetworkResult => getNetworkResult.Id)),
Service = "servicenetworking.googleapis.com",
ReservedPeeringRanges = new[]
{
privateIpAlloc.Name,
},
});
var sourceInstance = new Gcp.Alloydb.Instance("source", new()
{
Cluster = source.Name,
InstanceId = "alloydb-instance",
InstanceType = "PRIMARY",
MachineConfig = new Gcp.Alloydb.Inputs.InstanceMachineConfigArgs
{
CpuCount = 2,
},
}, new CustomResourceOptions
{
DependsOn =
{
vpcConnection,
},
});
var sourceBackup = new Gcp.Alloydb.Backup("source", new()
{
BackupId = "alloydb-backup",
Location = "us-central1",
ClusterName = source.Name,
}, new CustomResourceOptions
{
DependsOn =
{
sourceInstance,
},
});
var restoredFromBackup = new Gcp.Alloydb.Cluster("restored_from_backup", new()
{
ClusterId = "alloydb-backup-restored",
Location = "us-central1",
NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
{
Network = @default.Apply(@default => @default.Apply(getNetworkResult => getNetworkResult.Id)),
},
RestoreBackupSource = new Gcp.Alloydb.Inputs.ClusterRestoreBackupSourceArgs
{
BackupName = sourceBackup.Name,
},
DeletionProtection = false,
});
var restoredViaPitr = new Gcp.Alloydb.Cluster("restored_via_pitr", new()
{
ClusterId = "alloydb-pitr-restored",
Location = "us-central1",
NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
{
Network = @default.Apply(@default => @default.Apply(getNetworkResult => getNetworkResult.Id)),
},
RestoreContinuousBackupSource = new Gcp.Alloydb.Inputs.ClusterRestoreContinuousBackupSourceArgs
{
Cluster = source.Name,
PointInTime = "2023-08-03T19:19:00.094Z",
},
DeletionProtection = false,
});
var project = Gcp.Organizations.GetProject.Invoke();
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.ComputeFunctions;
import com.pulumi.gcp.compute.inputs.GetNetworkArgs;
import com.pulumi.gcp.alloydb.Cluster;
import com.pulumi.gcp.alloydb.ClusterArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterInitialUserArgs;
import com.pulumi.gcp.compute.GlobalAddress;
import com.pulumi.gcp.compute.GlobalAddressArgs;
import com.pulumi.gcp.servicenetworking.Connection;
import com.pulumi.gcp.servicenetworking.ConnectionArgs;
import com.pulumi.gcp.alloydb.Instance;
import com.pulumi.gcp.alloydb.InstanceArgs;
import com.pulumi.gcp.alloydb.inputs.InstanceMachineConfigArgs;
import com.pulumi.gcp.alloydb.Backup;
import com.pulumi.gcp.alloydb.BackupArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterNetworkConfigArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterRestoreBackupSourceArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterRestoreContinuousBackupSourceArgs;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var default = ComputeFunctions.getNetwork(GetNetworkArgs.builder()
.name("alloydb-network")
.build());
var source = new Cluster("source", ClusterArgs.builder()
.clusterId("alloydb-source-cluster")
.location("us-central1")
.network(default_.id())
.initialUser(ClusterInitialUserArgs.builder()
.password("alloydb-source-cluster")
.build())
.deletionProtection(false)
.build());
var privateIpAlloc = new GlobalAddress("privateIpAlloc", GlobalAddressArgs.builder()
.name("alloydb-source-cluster")
.addressType("INTERNAL")
.purpose("VPC_PEERING")
.prefixLength(16)
.network(default_.id())
.build());
var vpcConnection = new Connection("vpcConnection", ConnectionArgs.builder()
.network(default_.id())
.service("servicenetworking.googleapis.com")
.reservedPeeringRanges(privateIpAlloc.name())
.build());
var sourceInstance = new Instance("sourceInstance", InstanceArgs.builder()
.cluster(source.name())
.instanceId("alloydb-instance")
.instanceType("PRIMARY")
.machineConfig(InstanceMachineConfigArgs.builder()
.cpuCount(2)
.build())
.build(), CustomResourceOptions.builder()
.dependsOn(vpcConnection)
.build());
var sourceBackup = new Backup("sourceBackup", BackupArgs.builder()
.backupId("alloydb-backup")
.location("us-central1")
.clusterName(source.name())
.build(), CustomResourceOptions.builder()
.dependsOn(sourceInstance)
.build());
var restoredFromBackup = new Cluster("restoredFromBackup", ClusterArgs.builder()
.clusterId("alloydb-backup-restored")
.location("us-central1")
.networkConfig(ClusterNetworkConfigArgs.builder()
.network(default_.id())
.build())
.restoreBackupSource(ClusterRestoreBackupSourceArgs.builder()
.backupName(sourceBackup.name())
.build())
.deletionProtection(false)
.build());
var restoredViaPitr = new Cluster("restoredViaPitr", ClusterArgs.builder()
.clusterId("alloydb-pitr-restored")
.location("us-central1")
.networkConfig(ClusterNetworkConfigArgs.builder()
.network(default_.id())
.build())
.restoreContinuousBackupSource(ClusterRestoreContinuousBackupSourceArgs.builder()
.cluster(source.name())
.pointInTime("2023-08-03T19:19:00.094Z")
.build())
.deletionProtection(false)
.build());
final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
.build());
}
}
resources:
source:
type: gcp:alloydb:Cluster
properties:
clusterId: alloydb-source-cluster
location: us-central1
network: ${default.id}
initialUser:
password: alloydb-source-cluster
deletionProtection: false
sourceInstance:
type: gcp:alloydb:Instance
name: source
properties:
cluster: ${source.name}
instanceId: alloydb-instance
instanceType: PRIMARY
machineConfig:
cpuCount: 2
options:
dependsOn:
- ${vpcConnection}
sourceBackup:
type: gcp:alloydb:Backup
name: source
properties:
backupId: alloydb-backup
location: us-central1
clusterName: ${source.name}
options:
dependsOn:
- ${sourceInstance}
restoredFromBackup:
type: gcp:alloydb:Cluster
name: restored_from_backup
properties:
clusterId: alloydb-backup-restored
location: us-central1
networkConfig:
network: ${default.id}
restoreBackupSource:
backupName: ${sourceBackup.name}
deletionProtection: false
restoredViaPitr:
type: gcp:alloydb:Cluster
name: restored_via_pitr
properties:
clusterId: alloydb-pitr-restored
location: us-central1
networkConfig:
network: ${default.id}
restoreContinuousBackupSource:
cluster: ${source.name}
pointInTime: 2023-08-03T19:19:00.094Z
deletionProtection: false
privateIpAlloc:
type: gcp:compute:GlobalAddress
name: private_ip_alloc
properties:
name: alloydb-source-cluster
addressType: INTERNAL
purpose: VPC_PEERING
prefixLength: 16
network: ${default.id}
vpcConnection:
type: gcp:servicenetworking:Connection
name: vpc_connection
properties:
network: ${default.id}
service: servicenetworking.googleapis.com
reservedPeeringRanges:
- ${privateIpAlloc.name}
variables:
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
default:
fn::invoke:
function: gcp:compute:getNetwork
arguments:
name: alloydb-network
The restoreBackupSource property creates a cluster from a named backup, while restoreContinuousBackupSource restores to a specific pointInTime timestamp. These properties conflict with each other; use one or the other based on your recovery needs. The restored cluster becomes an independent primary cluster with its own backup policies.
Deploy a secondary cluster for cross-region replication
High-availability architectures replicate data across regions using secondary clusters that receive continuous replication from a primary cluster.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const _default = new gcp.compute.Network("default", {name: "alloydb-secondary-cluster"});
const primary = new gcp.alloydb.Cluster("primary", {
clusterId: "alloydb-primary-cluster",
location: "us-central1",
networkConfig: {
network: _default.id,
},
deletionProtection: false,
});
const privateIpAlloc = new gcp.compute.GlobalAddress("private_ip_alloc", {
name: "alloydb-secondary-cluster",
addressType: "INTERNAL",
purpose: "VPC_PEERING",
prefixLength: 16,
network: _default.id,
});
const vpcConnection = new gcp.servicenetworking.Connection("vpc_connection", {
network: _default.id,
service: "servicenetworking.googleapis.com",
reservedPeeringRanges: [privateIpAlloc.name],
});
const primaryInstance = new gcp.alloydb.Instance("primary", {
cluster: primary.name,
instanceId: "alloydb-primary-instance",
instanceType: "PRIMARY",
machineConfig: {
cpuCount: 2,
},
}, {
dependsOn: [vpcConnection],
});
const secondary = new gcp.alloydb.Cluster("secondary", {
clusterId: "alloydb-secondary-cluster",
location: "us-east1",
networkConfig: {
network: _default.id,
},
clusterType: "SECONDARY",
continuousBackupConfig: {
enabled: false,
},
secondaryConfig: {
primaryClusterName: primary.name,
},
deletionProtection: false,
}, {
dependsOn: [primaryInstance],
});
const project = gcp.organizations.getProject({});
import pulumi
import pulumi_gcp as gcp
default = gcp.compute.Network("default", name="alloydb-secondary-cluster")
primary = gcp.alloydb.Cluster("primary",
cluster_id="alloydb-primary-cluster",
location="us-central1",
network_config={
"network": default.id,
},
deletion_protection=False)
private_ip_alloc = gcp.compute.GlobalAddress("private_ip_alloc",
name="alloydb-secondary-cluster",
address_type="INTERNAL",
purpose="VPC_PEERING",
prefix_length=16,
network=default.id)
vpc_connection = gcp.servicenetworking.Connection("vpc_connection",
network=default.id,
service="servicenetworking.googleapis.com",
reserved_peering_ranges=[private_ip_alloc.name])
primary_instance = gcp.alloydb.Instance("primary",
cluster=primary.name,
instance_id="alloydb-primary-instance",
instance_type="PRIMARY",
machine_config={
"cpu_count": 2,
},
opts = pulumi.ResourceOptions(depends_on=[vpc_connection]))
secondary = gcp.alloydb.Cluster("secondary",
cluster_id="alloydb-secondary-cluster",
location="us-east1",
network_config={
"network": default.id,
},
cluster_type="SECONDARY",
continuous_backup_config={
"enabled": False,
},
secondary_config={
"primary_cluster_name": primary.name,
},
deletion_protection=False,
opts = pulumi.ResourceOptions(depends_on=[primary_instance]))
project = gcp.organizations.get_project()
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/alloydb"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/servicenetworking"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_default, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
Name: pulumi.String("alloydb-secondary-cluster"),
})
if err != nil {
return err
}
primary, err := alloydb.NewCluster(ctx, "primary", &alloydb.ClusterArgs{
ClusterId: pulumi.String("alloydb-primary-cluster"),
Location: pulumi.String("us-central1"),
NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
Network: _default.ID(),
},
DeletionProtection: pulumi.Bool(false),
})
if err != nil {
return err
}
privateIpAlloc, err := compute.NewGlobalAddress(ctx, "private_ip_alloc", &compute.GlobalAddressArgs{
Name: pulumi.String("alloydb-secondary-cluster"),
AddressType: pulumi.String("INTERNAL"),
Purpose: pulumi.String("VPC_PEERING"),
PrefixLength: pulumi.Int(16),
Network: _default.ID(),
})
if err != nil {
return err
}
vpcConnection, err := servicenetworking.NewConnection(ctx, "vpc_connection", &servicenetworking.ConnectionArgs{
Network: _default.ID(),
Service: pulumi.String("servicenetworking.googleapis.com"),
ReservedPeeringRanges: pulumi.StringArray{
privateIpAlloc.Name,
},
})
if err != nil {
return err
}
primaryInstance, err := alloydb.NewInstance(ctx, "primary", &alloydb.InstanceArgs{
Cluster: primary.Name,
InstanceId: pulumi.String("alloydb-primary-instance"),
InstanceType: pulumi.String("PRIMARY"),
MachineConfig: &alloydb.InstanceMachineConfigArgs{
CpuCount: pulumi.Int(2),
},
}, pulumi.DependsOn([]pulumi.Resource{
vpcConnection,
}))
if err != nil {
return err
}
_, err = alloydb.NewCluster(ctx, "secondary", &alloydb.ClusterArgs{
ClusterId: pulumi.String("alloydb-secondary-cluster"),
Location: pulumi.String("us-east1"),
NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
Network: _default.ID(),
},
ClusterType: pulumi.String("SECONDARY"),
ContinuousBackupConfig: &alloydb.ClusterContinuousBackupConfigArgs{
Enabled: pulumi.Bool(false),
},
SecondaryConfig: &alloydb.ClusterSecondaryConfigArgs{
PrimaryClusterName: primary.Name,
},
DeletionProtection: pulumi.Bool(false),
}, pulumi.DependsOn([]pulumi.Resource{
primaryInstance,
}))
if err != nil {
return err
}
_, err = organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
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 @default = new Gcp.Compute.Network("default", new()
{
Name = "alloydb-secondary-cluster",
});
var primary = new Gcp.Alloydb.Cluster("primary", new()
{
ClusterId = "alloydb-primary-cluster",
Location = "us-central1",
NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
{
Network = @default.Id,
},
DeletionProtection = false,
});
var privateIpAlloc = new Gcp.Compute.GlobalAddress("private_ip_alloc", new()
{
Name = "alloydb-secondary-cluster",
AddressType = "INTERNAL",
Purpose = "VPC_PEERING",
PrefixLength = 16,
Network = @default.Id,
});
var vpcConnection = new Gcp.ServiceNetworking.Connection("vpc_connection", new()
{
Network = @default.Id,
Service = "servicenetworking.googleapis.com",
ReservedPeeringRanges = new[]
{
privateIpAlloc.Name,
},
});
var primaryInstance = new Gcp.Alloydb.Instance("primary", new()
{
Cluster = primary.Name,
InstanceId = "alloydb-primary-instance",
InstanceType = "PRIMARY",
MachineConfig = new Gcp.Alloydb.Inputs.InstanceMachineConfigArgs
{
CpuCount = 2,
},
}, new CustomResourceOptions
{
DependsOn =
{
vpcConnection,
},
});
var secondary = new Gcp.Alloydb.Cluster("secondary", new()
{
ClusterId = "alloydb-secondary-cluster",
Location = "us-east1",
NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
{
Network = @default.Id,
},
ClusterType = "SECONDARY",
ContinuousBackupConfig = new Gcp.Alloydb.Inputs.ClusterContinuousBackupConfigArgs
{
Enabled = false,
},
SecondaryConfig = new Gcp.Alloydb.Inputs.ClusterSecondaryConfigArgs
{
PrimaryClusterName = primary.Name,
},
DeletionProtection = false,
}, new CustomResourceOptions
{
DependsOn =
{
primaryInstance,
},
});
var project = Gcp.Organizations.GetProject.Invoke();
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.alloydb.Cluster;
import com.pulumi.gcp.alloydb.ClusterArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterNetworkConfigArgs;
import com.pulumi.gcp.compute.GlobalAddress;
import com.pulumi.gcp.compute.GlobalAddressArgs;
import com.pulumi.gcp.servicenetworking.Connection;
import com.pulumi.gcp.servicenetworking.ConnectionArgs;
import com.pulumi.gcp.alloydb.Instance;
import com.pulumi.gcp.alloydb.InstanceArgs;
import com.pulumi.gcp.alloydb.inputs.InstanceMachineConfigArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterContinuousBackupConfigArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterSecondaryConfigArgs;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var default_ = new Network("default", NetworkArgs.builder()
.name("alloydb-secondary-cluster")
.build());
var primary = new Cluster("primary", ClusterArgs.builder()
.clusterId("alloydb-primary-cluster")
.location("us-central1")
.networkConfig(ClusterNetworkConfigArgs.builder()
.network(default_.id())
.build())
.deletionProtection(false)
.build());
var privateIpAlloc = new GlobalAddress("privateIpAlloc", GlobalAddressArgs.builder()
.name("alloydb-secondary-cluster")
.addressType("INTERNAL")
.purpose("VPC_PEERING")
.prefixLength(16)
.network(default_.id())
.build());
var vpcConnection = new Connection("vpcConnection", ConnectionArgs.builder()
.network(default_.id())
.service("servicenetworking.googleapis.com")
.reservedPeeringRanges(privateIpAlloc.name())
.build());
var primaryInstance = new Instance("primaryInstance", InstanceArgs.builder()
.cluster(primary.name())
.instanceId("alloydb-primary-instance")
.instanceType("PRIMARY")
.machineConfig(InstanceMachineConfigArgs.builder()
.cpuCount(2)
.build())
.build(), CustomResourceOptions.builder()
.dependsOn(vpcConnection)
.build());
var secondary = new Cluster("secondary", ClusterArgs.builder()
.clusterId("alloydb-secondary-cluster")
.location("us-east1")
.networkConfig(ClusterNetworkConfigArgs.builder()
.network(default_.id())
.build())
.clusterType("SECONDARY")
.continuousBackupConfig(ClusterContinuousBackupConfigArgs.builder()
.enabled(false)
.build())
.secondaryConfig(ClusterSecondaryConfigArgs.builder()
.primaryClusterName(primary.name())
.build())
.deletionProtection(false)
.build(), CustomResourceOptions.builder()
.dependsOn(primaryInstance)
.build());
final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
.build());
}
}
resources:
primary:
type: gcp:alloydb:Cluster
properties:
clusterId: alloydb-primary-cluster
location: us-central1
networkConfig:
network: ${default.id}
deletionProtection: false
primaryInstance:
type: gcp:alloydb:Instance
name: primary
properties:
cluster: ${primary.name}
instanceId: alloydb-primary-instance
instanceType: PRIMARY
machineConfig:
cpuCount: 2
options:
dependsOn:
- ${vpcConnection}
secondary:
type: gcp:alloydb:Cluster
properties:
clusterId: alloydb-secondary-cluster
location: us-east1
networkConfig:
network: ${default.id}
clusterType: SECONDARY
continuousBackupConfig:
enabled: false
secondaryConfig:
primaryClusterName: ${primary.name}
deletionProtection: false
options:
dependsOn:
- ${primaryInstance}
default:
type: gcp:compute:Network
properties:
name: alloydb-secondary-cluster
privateIpAlloc:
type: gcp:compute:GlobalAddress
name: private_ip_alloc
properties:
name: alloydb-secondary-cluster
addressType: INTERNAL
purpose: VPC_PEERING
prefixLength: 16
network: ${default.id}
vpcConnection:
type: gcp:servicenetworking:Connection
name: vpc_connection
properties:
network: ${default.id}
service: servicenetworking.googleapis.com
reservedPeeringRanges:
- ${privateIpAlloc.name}
variables:
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
The clusterType property set to SECONDARY designates this as a replica cluster. The secondaryConfig block references the primaryClusterName to establish replication. Secondary clusters require the primary cluster to have at least one instance running and VPC peering configured between regions. You can promote a secondary to primary by changing clusterType to PRIMARY and removing secondaryConfig.
Beyond these examples
These snippets focus on specific cluster-level features: cluster creation and network placement, backup policies, and cross-region replication with secondary clusters. They’re intentionally minimal rather than full database deployments.
The examples may reference pre-existing infrastructure such as VPC networks and subnets, VPC peering for cross-region connectivity, and source clusters and backups for restore scenarios. They focus on configuring the cluster rather than provisioning everything around it.
To keep things focused, common cluster patterns are omitted, including:
- Customer-managed encryption keys (encryptionConfig)
- Private Service Connect configuration (pscConfig)
- Maintenance update policies and windows
- Dataplex integration settings
- Major version upgrades (POSTGRES_14 to POSTGRES_15)
These omissions are intentional: the goal is to illustrate how each cluster feature is wired, not provide drop-in database modules. See the AlloyDB Cluster resource reference for all available configuration options.
Let's deploy GCP AlloyDB Clusters
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Cluster Types & Replication
cluster_type = "SECONDARY" and a secondary_config block pointing to the primary cluster.cluster_type to PRIMARY and remove the secondary_config field from your configuration.pulumi up -refresh-only --auto-approve to refresh state, 2) Manually update cluster_type and secondary_config in your code to match the actual state, 3) Run pulumi preview to verify no changes are required.Backup & Restore
You have two backup options:
- Continuous backup - Enabled by default, takes one backup per day and retains for 14 days (configurable via
continuous_backup_config) - Automated backup - Disabled by default, configure via
automated_backup_policyfor scheduled backups with custom retention
You can restore from four sources, but they’re mutually exclusive (choose only one):
- Backup restore -
restore_backup_sourcewith a backup name - Point-in-time recovery -
restore_continuous_backup_sourcewith cluster and timestamp - BackupDR backup -
restore_backupdr_backup_source - BackupDR PITR -
restore_backupdr_pitr_source
Database Upgrades
database_version to a higher version (e.g., POSTGRES_14 to POSTGRES_15) is an irreversible upgrade. Plan carefully before upgrading.skip_await_major_version_upgrade property defaults to true. Set it to false if you want Pulumi to wait for the upgrade to finish.Deletion & Protection
deletion_policy = "FORCE". There’s no support to delete just the secondary instance, so you must forcefully delete the entire cluster.deletion_protection is true or unset, pulumi up or destroy operations that would delete the cluster will fail. Set it to false to allow deletion.deletion_protection is a safety feature preventing accidental deletion. deletion_policy controls whether to forcefully delete clusters with instances (required for secondary clusters).Configuration & State Management
initial_user.password field is write-only and won’t be stored in Pulumi state for security. Store passwords securely outside of state.annotations and labels are non-authoritative, meaning Pulumi only manages the values in your configuration. Use effective_annotations and effective_labels output properties to see all annotations/labels present on the resource, including those set by other clients.network_config property is required and must specify the VPC network ID for the cluster, as shown in all examples.