Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an example of use of shared VPC networking. #810

Merged
merged 5 commits into from
Dec 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/shared-vpc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
terraform.tfstate
terraform.tfstate.backup
terraform.tfvars
24 changes: 24 additions & 0 deletions examples/shared-vpc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Shared Virtual Private Cloud Networking in Google Cloud

This is a template showcasing the shared VPC feature in Google Cloud. It features
four projects:
- A host project, which owns a VPC
- Two service projects, each of which owns a VM connected to the VPC
- A fourth project, which owns a VM not connected to the VPC.

It is based on the diagram in the overview at [https://cloud.google.com/vpc/docs/shared-vpc](https://cloud.google.com/vpc/docs/shared-vpc).

Begin by [downloading your credentials from Google Cloud Console](https://www.terraform.io/docs/providers/google/#credentials); the default path for the downloaded file is `~/.gcloud/Terraform.json`. If you use another path, update the `credentials_file_path` variable. Ensure that these credentials have Organization-level permissions - this example will create and administer projects.

This example creates projects within an organization - to run it, you will need to have an Organization ID. To get started using Organizations, read the quickstart [here](https://cloud.google.com/resource-manager/docs/quickstart-organizations). Since it uses organizations, project-specific credentials won't work, and consequently this example is configured to use [application default credentials](https://developers.google.com/identity/protocols/application-default-credentials). Ensure that the application default credentials have permission to create and manage projects and Shared VPCs (sometimes called 'XPN'). The example also requires you to specify a billing account, since it does start up a few VMs.

After you run `terraform apply` on this configuration, it will output the IP address of the second service project's VM, which (after it's done starting up) displays a page checking network connectivity to the other two VMs.

Run with a command like:
```
terraform apply \
-var="region=us-central1" \
-var="region_zone=us-central1-f" \
-var="org_id=1234567" \
-var="billing_account_id=XXXXXXXXXXXX"
```
251 changes: 251 additions & 0 deletions examples/shared-vpc/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
# https://cloud.google.com/vpc/docs/shared-vpc

provider "google" {
region = "${var.region}"
credentials = "${file("${var.credentials_file_path}")}"
}

provider "random" {}

resource "random_id" "host_project_name" {
byte_length = 8
}

resource "random_id" "service_project_1_name" {
byte_length = 8
}

resource "random_id" "service_project_2_name" {
byte_length = 8
}

resource "random_id" "standalone_project_name" {
byte_length = 8
}

# The project which owns the VPC.
resource "google_project" "host_project" {
name = "Host Project"
project_id = "tf-vpc-${random_id.host_project_name.hex}"
org_id = "${var.org_id}"
billing_account = "${var.billing_account_id}"
}

# One project which will use the VPC.
resource "google_project" "service_project_1" {
name = "Service Project 1"
project_id = "tf-vpc-${random_id.service_project_1_name.hex}"
org_id = "${var.org_id}"
billing_account = "${var.billing_account_id}"
}

# The other project which will use the VPC.
resource "google_project" "service_project_2" {
name = "Service Project 2"
project_id = "tf-vpc-${random_id.service_project_2_name.hex}"
org_id = "${var.org_id}"
billing_account = "${var.billing_account_id}"
}

# A project which will not use the VPC, for the sake of demonstration.
resource "google_project" "standalone_project" {
name = "Standalone Project"
project_id = "tf-vpc-${random_id.standalone_project_name.hex}"
org_id = "${var.org_id}"
billing_account = "${var.billing_account_id}"
}

# Compute service needs to be enabled for all four new projects.
resource "google_project_service" "host_project" {
project = "${google_project.host_project.project_id}"
service = "compute.googleapis.com"
}

resource "google_project_service" "service_project_1" {
project = "${google_project.service_project_1.project_id}"
service = "compute.googleapis.com"
}

resource "google_project_service" "service_project_2" {
project = "${google_project.service_project_2.project_id}"
service = "compute.googleapis.com"
}

resource "google_project_service" "standalone_project" {
project = "${google_project.standalone_project.project_id}"
service = "compute.googleapis.com"
}

# Enable shared VPC hosting in the host project.
resource "google_compute_shared_vpc_host_project" "host_project" {
project = "${google_project.host_project.project_id}"
depends_on = ["google_project_service.host_project"]
}

# Enable shared VPC in the two service projects - explicitly depend on the host
# project enabling it, because enabling shared VPC will fail if the host project
# is not yet hosting.
resource "google_compute_shared_vpc_service_project" "service_project_1" {
host_project = "${google_project.host_project.project_id}"
service_project = "${google_project.service_project_1.project_id}"

depends_on = ["google_compute_shared_vpc_host_project.host_project",
"google_project_service.service_project_1",
]
}

resource "google_compute_shared_vpc_service_project" "service_project_2" {
host_project = "${google_project.host_project.project_id}"
service_project = "${google_project.service_project_2.project_id}"

depends_on = ["google_compute_shared_vpc_host_project.host_project",
"google_project_service.service_project_2",
]
}

# Create the hosted network.
resource "google_compute_network" "shared_network" {
name = "shared-network"
auto_create_subnetworks = "true"
project = "${google_compute_shared_vpc_host_project.host_project.project}"

depends_on = ["google_compute_shared_vpc_service_project.service_project_1",
"google_compute_shared_vpc_service_project.service_project_2",
]
}

# Allow the hosted network to be hit over ICMP, SSH, and HTTP.
resource "google_compute_firewall" "shared_network" {
name = "allow-ssh-and-icmp"
network = "${google_compute_network.shared_network.self_link}"
project = "${google_compute_network.shared_network.project}"

allow {
protocol = "icmp"
}

allow {
protocol = "tcp"
ports = ["22", "80"]
}
}

# Create a standalone network with the same firewall rules.
resource "google_compute_network" "standalone_network" {
name = "standalone-network"
auto_create_subnetworks = "true"
project = "${google_project.standalone_project.project_id}"
depends_on = ["google_project_service.standalone_project"]
}

resource "google_compute_firewall" "standalone_network" {
name = "allow-ssh-and-icmp"
network = "${google_compute_network.standalone_network.self_link}"

allow {
protocol = "icmp"
}

allow {
protocol = "tcp"
ports = ["22", "80"]
}

project = "${google_project.standalone_project.project_id}"
}

# Create a VM which hosts a web page stating its identity ("VM1")
resource "google_compute_instance" "project_1_vm" {
name = "tf-project-1-vm"
project = "${google_project.service_project_1.project_id}"
machine_type = "f1-micro"
zone = "${var.region_zone}"

boot_disk {
initialize_params {
image = "projects/debian-cloud/global/images/family/debian-8"
}
}

metadata_startup_script = "VM_NAME=VM1\n${file("scripts/install-vm.sh")}"

network_interface {
network = "${google_compute_network.shared_network.self_link}"

access_config {
// Ephemeral IP
}
}

service_account {
scopes = ["https://www.googleapis.com/auth/compute.readonly"]
}

depends_on = ["google_project_service.service_project_1"]
}

# Create a VM which hosts a web page demonstrating the example networking.
resource "google_compute_instance" "project_2_vm" {
name = "tf-project-2-vm"
machine_type = "f1-micro"
project = "${google_project.service_project_2.project_id}"
zone = "${var.region_zone}"

boot_disk {
initialize_params {
image = "projects/debian-cloud/global/images/family/debian-8"
}
}

metadata_startup_script = <<EOF
VM1_EXT_IP=${google_compute_instance.project_1_vm.network_interface.0.access_config.0.assigned_nat_ip}
ST_VM_EXT_IP=${google_compute_instance.standalone_project_vm.network_interface.0.access_config.0.assigned_nat_ip}
VM1_INT_IP=${google_compute_instance.project_1_vm.network_interface.0.address}
ST_VM_INT_IP=${google_compute_instance.standalone_project_vm.network_interface.0.address}
${file("scripts/install-network-page.sh")}
EOF

network_interface {
network = "${google_compute_network.shared_network.self_link}"

access_config {
// Ephemeral IP
}
}

service_account {
scopes = ["https://www.googleapis.com/auth/compute.readonly"]
}

depends_on = ["google_project_service.service_project_2"]
}

# Create a VM which hosts a web page stating its identity ("standalone").
resource "google_compute_instance" "standalone_project_vm" {
name = "tf-standalone-vm"
machine_type = "f1-micro"
project = "${google_project.standalone_project.project_id}"
zone = "${var.region_zone}"

boot_disk {
initialize_params {
image = "projects/debian-cloud/global/images/family/debian-8"
}
}

metadata_startup_script = "VM_NAME=standalone\n${file("scripts/install-vm.sh")}"

network_interface {
network = "${google_compute_network.standalone_network.self_link}"

access_config {
// Ephemeral IP
}
}

service_account {
scopes = ["https://www.googleapis.com/auth/compute.readonly"]
}

depends_on = ["google_project_service.standalone_project"]
}
3 changes: 3 additions & 0 deletions examples/shared-vpc/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "status_page_public_ip" {
value = "${google_compute_instance.project_2_vm.network_interface.0.access_config.0.assigned_nat_ip}"
}
46 changes: 46 additions & 0 deletions examples/shared-vpc/scripts/install-network-page.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
sudo apt-get update
sudo apt-get install apache2 -y
sudo a2ensite default-ssl
sudo a2enmod ssl
sudo service apache2 restart
sudo cat > /var/www/html/index.html << EOF
<!doctype html><html><body>
<h1>Network Status for Shared VPC Terraform/Google Cloud Example</h1>
<h2>VM 1</h2>
<h3>Internal IP: $VM1_INT_IP</h3>
<pre>
$ ping -c 4 -W 1 $VM1_INT_IP
$(ping -c 4 -W 1 $VM1_INT_IP)

$ curl $VM1_INT_IP
$(curl $VM1_INT_IP)
</pre>
<h3>External IP: $VM1_EXT_IP</h3>
<pre>
$ ping -c 4 -W 1 $VM1_EXT_IP
$(ping -c 4 -W 1 $VM1_EXT_IP)

$ curl $VM1_EXT_IP
$(curl $VM1_EXT_IP)
</pre>
<h2>Standalone VM</h2>
<h3>Internal IP: $ST_VM_INT_IP</h3>
$(if [ $ST_VM_INT_IP = $VM1_INT_IP ]; then echo "<h4>Same internal IP as VM1</h4>"; fi)
<pre>
$ ping -c 4 -W 1 $ST_VM_INT_IP
$(ping -c 4 -W 1 $ST_VM_INT_IP)

$ curl $ST_VM_INT_IP
$(curl $ST_VM_INT_IP)
</pre>
<h3>External IP: $ST_VM_EXT_IP</h3>
<pre>
$ ping -c 4 -W 1 $ST_VM_EXT_IP
$(ping -c 4 -W 1 $ST_VM_EXT_IP)

$ curl $ST_VM_EXT_IP
$(curl $ST_VM_EXT_IP)
</pre>
</body></html>

EOF
6 changes: 6 additions & 0 deletions examples/shared-vpc/scripts/install-vm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
sudo apt-get update
sudo apt-get install apache2 -y
sudo a2ensite default-ssl
sudo a2enmod ssl
sudo service apache2 restart
echo "This is $VM_NAME" | sudo tee /var/www/html/index.html
4 changes: 4 additions & 0 deletions examples/shared-vpc/terraform.tfvars.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
region = "us-central1"
region_zone = "us-central1-b"
project_name = "my-project-id-123"
credentials_file_path = "~/.gcloud/Terraform.json"
20 changes: 20 additions & 0 deletions examples/shared-vpc/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
variable "region" {
default = "us-central1"
}

variable "region_zone" {
default = "us-central1-f"
}

variable "org_id" {
description = "The ID of the Google Cloud Organization."
}

variable "billing_account_id" {
description = "The ID of the associated billing account (optional)."
}

variable "credentials_file_path" {
description = "Location of the credentials to use."
default = "~/.gcloud/Terraform.json"
}