Skip to content

Commit 2232206

Browse files
committed
refactor!: gce-container-declaration deprecation
Due to the Compute Engine container startup agent deprecation on July 21 2025, GCP recommends now using a startup script or cloud-init to run containers in VMs. To avoid impacting users that already have startup scripts, this commit uses cloud-init to spin up the container. Changes: - Remove container module - Add service responsible for the Atlantis container - Changed `command` and `args` default values to `[]` instead of null, since we can't iterate null values Impact: - `google_compute_disk.persistent will be updated in-place` - `google_compute_instance_group_manager.default` will be updated in-place` - `google_compute_instance_template.default must be replaced` **Requires a couple minutes of downtime while the VM is restarted.** Sources: - https://cloud.google.com/compute/docs/deprecations/container-startup-agent-on-compute - https://cloud.google.com/compute/docs/containers/migrate-containers Signed-off-by: David Costa <33375428+d-costa@users.noreply.github.com>
1 parent ff48144 commit 2232206

3 files changed

Lines changed: 46 additions & 69 deletions

File tree

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,9 +204,7 @@ You can check the status of the certificate in the Google Cloud Console.
204204

205205
## Modules
206206

207-
| Name | Source | Version |
208-
|------|--------|---------|
209-
| <a name="module_container"></a> [container](#module\_container) | terraform-google-modules/container-vm/google | ~> 3.2 |
207+
No modules.
210208

211209
## Resources
212210

main.tf

Lines changed: 43 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ locals {
88
atlantis_network_traffic_tags = ["atlantis-${random_string.random.result}"]
99
atlantis_labels = merge(
1010
var.labels,
11-
module.container.container_vm.labels,
12-
{ "vm" = module.container.container_vm.name },
1311
{ "app" = "atlantis" }
1412
)
13+
atlantis_persistent_disk_name = "atlantis-disk-0"
14+
atlantis_disk_mount_path = "/mnt/disks/gce-containers-mounts/gce-persistent-disks/${local.atlantis_persistent_disk_name}"
15+
atlantis_uid = 100
1516
}
1617

1718
resource "random_string" "random" {
@@ -38,7 +39,20 @@ data "cloudinit_config" "config" {
3839
base64_encode = false
3940

4041
part {
41-
filename = "atlantis-chown-disk.service"
42+
filename = "runcmda"
43+
content_type = "text/cloud-config"
44+
merge_type = "list(append)+dict(no_replace, recurse_list)+str()"
45+
content = yamlencode({
46+
runcmd = [
47+
"systemctl daemon-reload",
48+
"systemctl start --no-block atlantis-chown-disk.service",
49+
"systemctl start --no-block atlantis.service"
50+
]
51+
})
52+
}
53+
54+
part {
55+
filename = "services"
4256
content_type = "text/cloud-config"
4357
content = yamlencode({
4458
write_files = [
@@ -49,10 +63,32 @@ data "cloudinit_config" "config" {
4963
content = <<EOF
5064
[Unit]
5165
Description=Change ownership of the mount path to the Atlantis uid
52-
Wants=konlet-startup.service
53-
After=konlet-startup.service
66+
Wants=docker.service
67+
After=docker.service
68+
[Service]
69+
ExecStart=/bin/chown ${local.atlantis_uid} ${local.atlantis_disk_mount_path}
70+
Restart=on-failure
71+
RestartSec=30
72+
StandardOutput=journal+console
73+
[Install]
74+
WantedBy=multi-user.target
75+
EOF
76+
},
77+
# https://cloud.google.com/container-optimized-os/docs/how-to/create-configure-instance#use-cloud-init
78+
# we are specifying `--publish 0.0.0.0` since `--network host` was binding to an ipv6 port.
79+
{
80+
path = "/etc/systemd/system/atlantis.service"
81+
permissions = "0644"
82+
owner = "root"
83+
content = <<EOF
84+
[Unit]
85+
Description=Start atlantis container
86+
Wants=atlantis-chown-disk.service
87+
After=atlantis-chown-disk.service
5488
[Service]
55-
ExecStart=/bin/chown 100 /mnt/disks/gce-containers-mounts/gce-persistent-disks/atlantis-disk-0
89+
ExecStart=/usr/bin/docker run -u ${local.atlantis_uid} --rm --publish '0.0.0.0:${local.atlantis_port}:${local.atlantis_port}' -v ${local.atlantis_disk_mount_path}:${local.atlantis_data_dir} %{for key, value in var.env_vars} -e '${key}=${value}'%{endfor} --name=atlantis ${var.image} ${join(" ", var.command)} ${join(" ", var.args)}
90+
ExecStop=/usr/bin/docker stop atlantis
91+
ExecStopPost=/usr/bin/docker rm atlantis
5692
Restart=on-failure
5793
RestartSec=30
5894
StandardOutput=journal+console
@@ -63,62 +99,6 @@ data "cloudinit_config" "config" {
6399
]
64100
})
65101
}
66-
67-
part {
68-
filename = "runcmda"
69-
content_type = "text/cloud-config"
70-
merge_type = "list(append)+dict(no_replace, recurse_list)+str()"
71-
content = yamlencode({
72-
runcmd = [
73-
"systemctl daemon-reload",
74-
"systemctl start --no-block atlantis-chown-disk.service"
75-
]
76-
})
77-
}
78-
}
79-
80-
module "container" {
81-
source = "terraform-google-modules/container-vm/google"
82-
version = "~> 3.2"
83-
84-
cos_image_name = var.machine_image != null ? element(split("/", var.machine_image), length(split("/", var.machine_image)) - 1) : null
85-
86-
container = {
87-
image = var.image
88-
securityContext = {
89-
privileged = false
90-
}
91-
tty = true
92-
env = [for key, value in var.env_vars : {
93-
name = key
94-
value = value
95-
}]
96-
command = var.command
97-
args = var.args
98-
99-
# Declare volumes to be mounted.
100-
# This is similar to how docker volumes are declared.
101-
volumeMounts = [
102-
{
103-
mountPath = local.atlantis_data_dir
104-
name = "atlantis-disk-0"
105-
readOnly = false
106-
},
107-
]
108-
}
109-
110-
volumes = [
111-
{
112-
name = "atlantis-disk-0"
113-
114-
gcePersistentDisk = {
115-
pdName = "atlantis-disk-0"
116-
fsType = "ext4"
117-
}
118-
},
119-
]
120-
121-
restart_policy = "Always"
122102
}
123103

124104
resource "google_compute_instance_template" "default" {
@@ -131,7 +111,6 @@ resource "google_compute_instance_template" "default" {
131111
metadata_startup_script = var.startup_script
132112

133113
metadata = {
134-
gce-container-declaration = module.container.metadata_value
135114
user-data = data.cloudinit_config.config.rendered
136115
google-logging-enabled = var.google_logging_enabled
137116
google-monitoring-enabled = var.google_monitoring_enabled
@@ -174,7 +153,7 @@ resource "google_compute_instance_template" "default" {
174153

175154
# Persistent disk for Atlantis
176155
disk {
177-
device_name = "atlantis-disk-0"
156+
device_name = local.atlantis_persistent_disk_name
178157
disk_type = var.persistent_disk_type
179158
mode = "READ_WRITE"
180159
disk_size_gb = var.persistent_disk_size_gb

variables.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,13 @@ variable "image" {
6868
variable "command" {
6969
type = list(string)
7070
description = "Command to override the container image ENTRYPOINT"
71-
default = null
71+
default = []
7272
}
7373

7474
variable "args" {
7575
type = list(string)
7676
description = "Arguments to override the container image default command (CMD)."
77-
default = null
77+
default = []
7878
}
7979

8080
variable "env_vars" {

0 commit comments

Comments
 (0)