Skip to content

Commit

Permalink
feat: redeploy strategy without recreating of the server (#1466)
Browse files Browse the repository at this point in the history
  • Loading branch information
wtools-bot authored Oct 17, 2024
1 parent 4a090ae commit fee816b
Show file tree
Hide file tree
Showing 16 changed files with 153 additions and 118 deletions.
2 changes: 1 addition & 1 deletion module/alias/cargo_will/src/bin/willbe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#[ allow( unused_imports ) ]
use::willbe::*;

fn main() -> Result< (), wtools::error::untyped::Error >
fn main() -> Result< (), error::untyped::Error >
{
Ok( willbe::run( std::env::args().collect() )? )
}
14 changes: 5 additions & 9 deletions module/move/willbe/src/action/deploy_renew.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,34 +47,30 @@ mod private
.file().data( include_str!( "../../template/deploy/key/pack.sh" ) ).path( "./key/pack.sh" ).end()
.file().data( include_str!( "../../template/deploy/key/Readme.md" ) ).path( "./key/Readme.md" ).end()
// /deploy/
.file().data( include_str!( "../../template/deploy/deploy/redeploy.sh" ) ).path( "./deploy/redeploy.sh" ).end()
.file().data( include_str!( "../../template/deploy/deploy/cloud-init.tpl.hbs" ) ).path( "./deploy/cloud-init.tpl" ).is_template( true ).end()
.file().data( include_str!( "../../template/deploy/deploy/Dockerfile" ) ).path( "./deploy/Dockerfile" ).end()
.file().data( include_str!( "../../template/deploy/deploy/Readme.md" ) ).path( "./deploy/Readme.md" ).end()
// /deploy/gar
.file().data( include_str!( "../../template/deploy/deploy/gar/Readme.md" ) ).path( "./deploy/gar/Readme.md" ).end()
.file().data( include_str!( "../../template/deploy/deploy/gar/main.tf" ) ).path( "./deploy/gar/main.tf" ).end()
.file().data( include_str!( "../../template/deploy/deploy/gar/main.tf.hbs" ) ).path( "./deploy/gar/main.tf" ).is_template( true ).end()
.file().data( include_str!( "../../template/deploy/deploy/gar/outputs.tf" ) ).path( "./deploy/gar/outputs.tf" ).end()
.file().data( include_str!( "../../template/deploy/deploy/gar/variables.tf" ) ).path( "./deploy/gar/variables.tf" ).end()
// /deploy/gce
.file().data( include_str!( "../../template/deploy/deploy/gce/Readme.md" ) ).path( "./deploy/gce/Readme.md" ).end()
.file().data( include_str!( "../../template/deploy/deploy/gce/main.tf" ) ).path( "./deploy/gce/main.tf" ).end()
.file().data( include_str!( "../../template/deploy/deploy/gce/outputs.tf" ) ).path( "./deploy/gce/outputs.tf" ).end()
.file().data( include_str!( "../../template/deploy/deploy/gce/main.tf.hbs" ) ).path( "./deploy/gce/main.tf" ).is_template( true ).end()
.file().data( include_str!( "../../template/deploy/deploy/gce/outputs.tf.hbs" ) ).path( "./deploy/gce/outputs.tf" ).is_template( true ).end()
.file().data( include_str!( "../../template/deploy/deploy/gce/variables.tf" ) ).path( "./deploy/gce/variables.tf" ).end()
// /deploy/gce/templates
.file().data( include_str!( "../../template/deploy/deploy/gce/templates/cloud-init.tpl" ) ).path( "./deploy/gce/templates/cloud-init.tpl" ).end()
// /deploy/gcs
.file().data( include_str!( "../../template/deploy/deploy/gcs/main.tf" ) ).path( "./deploy/gcs/main.tf" ).end()
// /deploy/hetzner
.file().data( include_str!( "../../template/deploy/deploy/hetzner/main.tf.hbs" ) ).path( "./deploy/hetzner/main.tf" ).is_template( true ).end()
.file().data( include_str!( "../../template/deploy/deploy/hetzner/outputs.tf.hbs" ) ).path( "./deploy/hetzner/outputs.tf" ).is_template( true ).end()
.file().data( include_str!( "../../template/deploy/deploy/hetzner/variables.tf" ) ).path( "./deploy/hetzner/variables.tf" ).end()
// /deploy/hetzner/templates
.file().data( include_str!( "../../template/deploy/deploy/hetzner/templates/cloud-init.tpl.hbs" ) ).path( "./deploy/hetzner/templates/cloud-init.tpl" ).end()
// /deploy/aws
.file().data( include_str!( "../../template/deploy/deploy/aws/main.tf" ) ).path( "./deploy/aws/main.tf" ).end()
.file().data( include_str!( "../../template/deploy/deploy/aws/outputs.tf" ) ).path( "./deploy/aws/outputs.tf" ).end()
.file().data( include_str!( "../../template/deploy/deploy/aws/variables.tf" ) ).path( "./deploy/aws/variables.tf" ).end()
// /deploy/aws/templates
.file().data( include_str!( "../../template/deploy/deploy/aws/templates/cloud-init.tpl.hbs" ) ).path( "./deploy/aws/templates/cloud-init.tpl" ).is_template( true ).end()
.form();

formed.files
Expand Down
4 changes: 4 additions & 0 deletions module/move/willbe/template/deploy/Makefile.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,7 @@ state_storage_pull:
state_storage_init:
terraform -chdir=$(tf_dir)/gcs init
terraform -chdir=$(tf_dir)/gcs apply

# Destroys GCS Bucket for terraform states
state_storage_destroy:
terraform -chdir=$(tf_dir)/gcs destroy
2 changes: 1 addition & 1 deletion module/move/willbe/template/deploy/deploy/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ ENV TF_VERSION=1.7.4

WORKDIR /

# Installation terraform
# Install terraform
RUN apt update --allow-releaseinfo-change \
&& apt install wget unzip \
&& mkdir -p /usr/lib/terraform/${TF_VERSION} \
Expand Down
37 changes: 33 additions & 4 deletions module/move/willbe/template/deploy/deploy/aws/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,50 @@ resource "aws_instance" "web" {
associate_public_ip_address = true

# Startup script for the instance
# Installs docker, gcloud CLI, downloads docker images and starts the container
user_data = templatefile("${path.module}/templates/cloud-init.tpl", {
# Installs docker and gcloud CLI
user_data = templatefile("${path.module}/../cloud-init.tpl", {
location = "${var.REGION}"
project_id = "${var.PROJECT_ID}"
repo_name = "${var.REPO_NAME}"
image_name = "${var.IMAGE_NAME}"
service_account_creds = "${replace(data.local_sensitive_file.service_account_creds.content, "\n", "")}"
timestamp = "${timestamp()}"
})

user_data_replace_on_change = true
key_name = aws_key_pair.redeploy.key_name
}

# Static IP address for the instace that will persist on restarts and redeploys
resource "aws_eip" "static" {
instance = aws_instance.web.id
domain = "vpc"
}

resource "aws_key_pair" "redeploy" {
public_key = data.local_sensitive_file.ssh_public_key.content
}

resource "terraform_data" "redeploy" {
triggers_replace = timestamp()

connection {
type = "ssh"
user = "ubuntu"
private_key = data.local_sensitive_file.ssh_private_key.content
host = aws_eip.static.public_ip
}

provisioner "file" {
source = "${path.module}/../redeploy.sh"
destination = "/tmp/redeploy.sh"
}

provisioner "remote-exec" {
inline = [
"#!/bin/bash",
"( tail -f -n1 /var/log/deploy-init.log & ) | grep -q 'Docker configuration file updated.'",
"source /etc/environment",
"chmod +x /tmp/redeploy.sh",
"sudo /tmp/redeploy.sh"
]
}
}

This file was deleted.

10 changes: 10 additions & 0 deletions module/move/willbe/template/deploy/deploy/aws/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,13 @@ variable "IMAGE_NAME" {
data "local_sensitive_file" "service_account_creds" {
filename = "${path.module}/../../key/service_account.json"
}

# Private key for SSH connection
data "local_sensitive_file" "ssh_private_key" {
filename = "${path.module}/../../key/rsa_ssh_key"
}

# Public key for SSH connection
data "local_sensitive_file" "ssh_public_key" {
filename = "${path.module}/../../key/rsa_ssh_key.pub"
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
#cloud-config

write_files:
- path: /etc/systemd/system/${image_name}.service
permissions: 0644
owner: root
content: |
[Unit]
Description=Start ${image_name} docker container. Build: ${timestamp}
Wants=network-online.target
After=network-online.target

[Service]
Environment="HOME=/root"
ExecStart=/usr/bin/docker run -d -p 80:80 --name=${image_name} ${location}-docker.pkg.dev/${project_id}/${repo_name}/${image_name}
- path: /root/service_account.json
permissions: 0600
owner: root
Expand All @@ -22,6 +10,10 @@ write_files:
permissions: 0700
owner: root
content: |
# Configure env for redeploy script
echo "DOCKER_IMAGE=${location}-docker.pkg.dev/${project_id}/${repo_name}/${image_name}" >> /etc/environment
echo "DOCKER_IMAGE_NAME=${image_name}" >> /etc/environment

# Install docker
apt update
apt install apt-transport-https ca-certificates curl software-properties-common -y
Expand All @@ -37,10 +29,7 @@ write_files:
# Configure docker with gcloud
gcloud auth activate-service-account --key-file=/root/service_account.json
gcloud auth configure-docker ${location}-docker.pkg.dev --quiet
# Start docker container
systemctl daemon-reload
systemctl start ${image_name}.service


runcmd:
- nohup /root/init.sh > /var/log/{{docker_image_name}}-instance-init.log 2>&1 &
- nohup /root/init.sh > /var/log/deploy-init.log 2>&1 &
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ resource "google_artifact_registry_repository" "container-images-repo" {
location = var.REGION
project = var.PROJECT_ID
repository_id = var.REPO_NAME
description = "Docker image registry for the Learn Together web-site"
description = "Docker image registry for the {{docker_image_name}} deployments"
# Format of the repository. We are using Docker.
format = "DOCKER"
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
locals {
# Helper var for formatting docker image name
image_name = format("%s-docker.pkg.dev/%s/%s/%s", var.REGION, var.PROJECT_ID, var.REPO_NAME, var.IMAGE_NAME)
image_name = format("%s-docker.pkg.dev/%s/%s/%s", var.REGION, var.PROJECT_ID, var.REPO_NAME, var.IMAGE_NAME)
# Helper var for formatting subnetwork for our instance
subnetwork = format("projects/%s/regions/%s/subnetworks/default", var.PROJECT_ID, var.REGION)
instance_name = format("ltsite-%s", formatdate("YYYYMMDDhhmmss", timestamp()))
subnetwork = format("projects/%s/regions/%s/subnetworks/default", var.PROJECT_ID, var.REGION)
}

# Provider for resource creation
Expand All @@ -18,23 +17,23 @@ resource "google_compute_address" "default" {
}

# GCE instance block.
resource "google_compute_instance" "lts-container-vm" {
project = var.PROJECT_ID
resource "google_compute_instance" "{{docker_image_name}}" {
project = var.PROJECT_ID
# Instance name
name = local.instance_name
name = "{{docker_image_name}}"
# Instance size. e2-micro is 0.25-2 vCPU & 1GB RAM
machine_type = "e2-micro"
zone = var.ZONE

# Main disk options
boot_disk {
initialize_params {
# Disk image name. We're using Container-optimised OS (COS).
image = "projects/cos-cloud/global/images/cos-stable-109-17800-147-15"
# Disk image name. We're using Ubuntu 24.04 distro.
image = "projects/ubuntu-os-cloud/global/images/ubuntu-2404-noble-amd64-v20241004"
# Disk size in GB. 10GB is allowed minimum.
size = 10
size = 10
# Disk type. Possible values: pd-standard, pd-ssd, or pd-balanced.
type = "pd-balanced"
type = "pd-balanced"
}
}

Expand All @@ -52,19 +51,20 @@ resource "google_compute_instance" "lts-container-vm" {
metadata = {
# Cloud-init startup script for configuring the instance with our docker container.
user-data = "${data.cloudinit_config.conf.rendered}"
ssh-keys = "root:${data.local_sensitive_file.ssh_public_key.content}"
}

allow_stopping_for_update = true

scheduling {
# Restart on failure.
automatic_restart = true
automatic_restart = true
# Describes maintenance behavior for the instance. Possible values: MIGRATE or TERMINATE.
on_host_maintenance = "MIGRATE"
# Configures whether to allow stopping instance at any moment for reduced cost.
preemptible = false
preemptible = false
# Configures spot instance. Possible values: SPOT or STANDARD.
provisioning_model = "STANDARD"
provisioning_model = "STANDARD"
}

# Configues service account scopes.
Expand All @@ -86,3 +86,29 @@ resource "google_compute_instance" "lts-container-vm" {
# Use `https-server` for https traffic on port 443.
tags = ["http-server"]
}

resource "terraform_data" "redeploy" {
triggers_replace = timestamp()

connection {
type = "ssh"
user = "root"
private_key = data.local_sensitive_file.ssh_private_key.content
host = google_compute_instance.{{docker_image_name}}.network_interface[0].access_config[0].nat_ip
}

provisioner "file" {
source = "${path.module}/../redeploy.sh"
destination = "/tmp/redeploy.sh"
}

provisioner "remote-exec" {
inline = [
"#!/bin/bash",
"( tail -f -n1 /var/log/deploy-init.log & ) | grep -q 'Docker configuration file updated.'",
"source /etc/environment",
"chmod +x /tmp/redeploy.sh",
"/tmp/redeploy.sh"
]
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
locals {
ip = google_compute_instance.lts-container-vm.network_interface[0].access_config[0].nat_ip
ip = google_compute_instance.{{docker_image_name}}.network_interface[0].access_config[0].nat_ip
}

# Output that we get after applying.
Expand Down

This file was deleted.

Loading

0 comments on commit fee816b

Please sign in to comment.