This repository has been archived by the owner on Mar 29, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 117
/
main.tf
312 lines (245 loc) · 9.41 KB
/
main.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# ---------------------------------------------------------------------------------------------------------------------
# LAUNCH A LOAD BALANCER WITH INSTANCE GROUP AND STORAGE BUCKET BACKEND
#
# This is an example of how to use the http-load-balancer module to deploy a HTTP load balancer
# with multiple backends and optionally ssl and custom domain.
# ---------------------------------------------------------------------------------------------------------------------
terraform {
# This module is now only being tested with Terraform 1.0.x. However, to make upgrading easier, we are setting
# 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it
# forwards compatible with 1.0.x code.
required_version = ">= 0.12.26"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 3.43.0"
}
google-beta = {
source = "hashicorp/google-beta"
version = "~> 3.43.0"
}
}
}
# ------------------------------------------------------------------------------
# CONFIGURE OUR GCP CONNECTION
# ------------------------------------------------------------------------------
provider "google" {
region = var.region
project = var.project
}
provider "google-beta" {
region = var.region
project = var.project
}
# ------------------------------------------------------------------------------
# CREATE THE LOAD BALANCER
# ------------------------------------------------------------------------------
module "lb" {
source = "./modules/http-load-balancer"
name = var.name
project = var.project
url_map = google_compute_url_map.urlmap.self_link
dns_managed_zone_name = var.dns_managed_zone_name
custom_domain_names = [var.custom_domain_name]
create_dns_entries = var.create_dns_entry
dns_record_ttl = var.dns_record_ttl
enable_http = var.enable_http
enable_ssl = var.enable_ssl
ssl_certificates = google_compute_ssl_certificate.certificate.*.self_link
custom_labels = var.custom_labels
}
# ------------------------------------------------------------------------------
# CREATE THE URL MAP TO MAP PATHS TO BACKENDS
# ------------------------------------------------------------------------------
resource "google_compute_url_map" "urlmap" {
project = var.project
name = "${var.name}-url-map"
description = "URL map for ${var.name}"
default_service = google_compute_backend_bucket.static.self_link
host_rule {
hosts = ["*"]
path_matcher = "all"
}
path_matcher {
name = "all"
default_service = google_compute_backend_bucket.static.self_link
path_rule {
paths = ["/api", "/api/*"]
service = google_compute_backend_service.api.self_link
}
}
}
# ------------------------------------------------------------------------------
# CREATE THE BACKEND SERVICE CONFIGURATION FOR THE INSTANCE GROUP
# ------------------------------------------------------------------------------
resource "google_compute_backend_service" "api" {
project = var.project
name = "${var.name}-api"
description = "API Backend for ${var.name}"
port_name = "http"
protocol = "HTTP"
timeout_sec = 10
enable_cdn = false
backend {
group = google_compute_instance_group.api.self_link
}
health_checks = [google_compute_health_check.default.self_link]
depends_on = [google_compute_instance_group.api]
}
# ------------------------------------------------------------------------------
# CONFIGURE HEALTH CHECK FOR THE API BACKEND
# ------------------------------------------------------------------------------
resource "google_compute_health_check" "default" {
project = var.project
name = "${var.name}-hc"
http_health_check {
port = 5000
request_path = "/api"
}
check_interval_sec = 5
timeout_sec = 5
}
# ------------------------------------------------------------------------------
# CREATE THE STORAGE BUCKET FOR THE STATIC CONTENT
# ------------------------------------------------------------------------------
resource "google_storage_bucket" "static" {
project = var.project
name = "${var.name}-bucket"
location = var.static_content_bucket_location
storage_class = "MULTI_REGIONAL"
website {
main_page_suffix = "index.html"
not_found_page = "404.html"
}
# For the example, we want to clean up all resources. In production, you should set this to false to prevent
# accidental loss of data
force_destroy = true
labels = var.custom_labels
}
# ------------------------------------------------------------------------------
# CREATE THE BACKEND FOR THE STORAGE BUCKET
# ------------------------------------------------------------------------------
resource "google_compute_backend_bucket" "static" {
project = var.project
name = "${var.name}-backend-bucket"
bucket_name = google_storage_bucket.static.name
}
# ------------------------------------------------------------------------------
# UPLOAD SAMPLE CONTENT WITH PUBLIC READ ACCESS
# ------------------------------------------------------------------------------
resource "google_storage_default_object_acl" "website_acl" {
bucket = google_storage_bucket.static.name
role_entity = ["READER:allUsers"]
}
resource "google_storage_bucket_object" "index" {
name = "index.html"
content = "Hello, World!"
bucket = google_storage_bucket.static.name
# We have to depend on the ACL because otherwise the ACL could get created after the object
depends_on = [google_storage_default_object_acl.website_acl]
}
resource "google_storage_bucket_object" "not_found" {
name = "404.html"
content = "Uh oh"
bucket = google_storage_bucket.static.name
# We have to depend on the ACL because otherwise the ACL could get created after the object
depends_on = [google_storage_default_object_acl.website_acl]
}
# ------------------------------------------------------------------------------
# IF SSL IS ENABLED, CREATE A SELF-SIGNED CERTIFICATE
# ------------------------------------------------------------------------------
resource "tls_self_signed_cert" "cert" {
# Only create if SSL is enabled
count = var.enable_ssl ? 1 : 0
key_algorithm = "RSA"
private_key_pem = join("", tls_private_key.private_key.*.private_key_pem)
subject {
common_name = var.custom_domain_name
organization = "Examples, Inc"
}
validity_period_hours = 12
allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth",
]
}
resource "tls_private_key" "private_key" {
count = var.enable_ssl ? 1 : 0
algorithm = "RSA"
ecdsa_curve = "P256"
}
# ------------------------------------------------------------------------------
# CREATE A CORRESPONDING GOOGLE CERTIFICATE THAT WE CAN ATTACH TO THE LOAD BALANCER
# ------------------------------------------------------------------------------
resource "google_compute_ssl_certificate" "certificate" {
project = var.project
count = var.enable_ssl ? 1 : 0
name_prefix = var.name
description = "SSL Certificate"
private_key = join("", tls_private_key.private_key.*.private_key_pem)
certificate = join("", tls_self_signed_cert.cert.*.cert_pem)
lifecycle {
create_before_destroy = true
}
}
# ------------------------------------------------------------------------------
# CREATE THE INSTANCE GROUP WITH A SINGLE INSTANCE AND THE BACKEND SERVICE CONFIGURATION
#
# We use the instance group only to highlight the ability to specify multiple types
# of backends for the load balancer
# ------------------------------------------------------------------------------
resource "google_compute_instance_group" "api" {
project = var.project
name = "${var.name}-instance-group"
zone = var.zone
instances = [google_compute_instance.api.self_link]
lifecycle {
create_before_destroy = true
}
named_port {
name = "http"
port = 5000
}
}
resource "google_compute_instance" "api" {
project = var.project
name = "${var.name}-instance"
machine_type = "f1-micro"
zone = var.zone
# We're tagging the instance with the tag specified in the firewall rule
tags = ["private-app"]
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
# Make sure we have the flask application running
metadata_startup_script = file("${path.module}/examples/shared/startup_script.sh")
# Launch the instance in the default subnetwork
network_interface {
subnetwork = "default"
# This gives the instance a public IP address for internet connectivity. Normally, you would have a Cloud NAT,
# but for the sake of simplicity, we're assigning a public IP to get internet connectivity
# to be able to run startup scripts
access_config {
}
}
}
# ------------------------------------------------------------------------------
# CREATE A FIREWALL TO ALLOW ACCESS FROM THE LB TO THE INSTANCE
# ------------------------------------------------------------------------------
resource "google_compute_firewall" "firewall" {
project = var.project
name = "${var.name}-fw"
network = "default"
# Allow load balancer access to the API instances
# https://cloud.google.com/load-balancing/docs/https/#firewall_rules
source_ranges = ["130.211.0.0/22", "35.191.0.0/16"]
target_tags = ["private-app"]
source_tags = ["private-app"]
allow {
protocol = "tcp"
ports = ["5000"]
}
}