From 859302774c4d719cf949f419d0efcfd8cbad6ca2 Mon Sep 17 00:00:00 2001 From: Christopher Baines Date: Mon, 27 May 2019 21:35:53 +0100 Subject: Add a new AWS backend using Amazon Machine Images The existing AWS backend uses system containers backed on to the AWS hosted NFS service (EFS). This has some advantages, but also some disadvantages. Using the EFS service allows building a container on one instance, with the state being held on the EFS, and then launching a new instance to run the container. Using EFS also provides persistence, at least beyond individual EC2 instances. However, build performance when using EFS is poor compared with a local store without the overhead of the network latency. Additionally, the startup speed of the container running off EFS is slow compared to local storage. This backend doesn't use EFS, instead the Guix store sits on instance storage. Rather than using a system container for a Mini Environment, an Amazon Machine Image (AMI) is built instead. The fast local storage makes builds faster, and using EBS storage for the Mini Envirnoments as well as not having the overhead of starting Ubuntu, then starting the container also makes startup faster. --- .../aws_using_ami/backend/guix-daemon.service.tpl | 17 + terraform/aws_using_ami/backend/main.tf | 437 +++++++++++++++++++++ terraform/aws_using_ami/mini_environment/main.tf | 114 ++++++ 3 files changed, 568 insertions(+) create mode 100644 terraform/aws_using_ami/backend/guix-daemon.service.tpl create mode 100644 terraform/aws_using_ami/backend/main.tf create mode 100644 terraform/aws_using_ami/mini_environment/main.tf (limited to 'terraform') diff --git a/terraform/aws_using_ami/backend/guix-daemon.service.tpl b/terraform/aws_using_ami/backend/guix-daemon.service.tpl new file mode 100644 index 0000000..184e3d5 --- /dev/null +++ b/terraform/aws_using_ami/backend/guix-daemon.service.tpl @@ -0,0 +1,17 @@ +[Unit] +Description=Build daemon for GNU Guix + +[Service] +ExecStart=/var/guix/profiles/per-user/root/current-guix/bin/guix-daemon --build-users-group=guixbuild --substitute-urls="${substitute_servers}" --listen=0.0.0.0 --listen=/var/guix/daemon-socket/socket --max-jobs=4 +Environment=GUIX_LOCPATH='/var/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8 TMPDIR=/gnu/tmp +RemainAfterExit=yes +StandardOutput=syslog +StandardError=syslog + +# See . +# Some package builds (for example, go@1.8.1) may require even more than +# 1024 tasks. +TasksMax=8192 + +[Install] +WantedBy=multi-user.target diff --git a/terraform/aws_using_ami/backend/main.tf b/terraform/aws_using_ami/backend/main.tf new file mode 100644 index 0000000..fead443 --- /dev/null +++ b/terraform/aws_using_ami/backend/main.tf @@ -0,0 +1,437 @@ +terraform { + backend "http" {} +} + +variable "aws_access_key" { + type = "string" +} + +variable "aws_secret_key" { + type = "string" +} + +variable "aws_region" { + type = "string" +} + +variable "aws_vpc_id" { + type = "string" +} + +variable "aws_route_53_zone_id" { + type = "string" +} + +variable "ssh_public_key" { + type = "string" +} + +variable "ssh_private_key" { + type = "string" +} + +variable "guix_substitute_servers" { + type = "map" + default = { + "https://ci.guix.gnu.org" = < temp && mv temp .bashrc +EOF + ] + + connection { + type = "ssh" + user = "ubuntu" + private_key = "${var.ssh_private_key}" + } + } +} + +resource "aws_route53_record" "main" { + zone_id = "${data.aws_route53_zone.main.zone_id}" + name = "builder.${var.backend_slug}" + type = "A" + ttl = "60" + records = ["${aws_spot_instance_request.main.public_ip}"] + + depends_on = ["aws_spot_instance_request.main"] +} + +# Outputs + +output "backend_up" { + value = "${length(aws_spot_instance_request.main.public_ip) != 0}" +} + +output "deployer_key_pair_name" { + value = "${aws_key_pair.deployer.key_name}" +} + +output "guix_client_security_group_name" { + value = "${aws_security_group.guix_client.name}" +} + +output "public_webserver_security_group_name" { + value = "${aws_security_group.public_webserver.name}" +} + +output "ssh_access_from_mini_environment_admin_security_group_name" { + value = "${aws_security_group.ssh_access_from_mini_environment_admin.name}" +} + +output "guix_daemon_private_dns" { + value = "${aws_spot_instance_request.main.private_dns}" +} + +output "guix_daemon_public_dns" { + value = "${aws_spot_instance_request.main.public_dns}" +} diff --git a/terraform/aws_using_ami/mini_environment/main.tf b/terraform/aws_using_ami/mini_environment/main.tf new file mode 100644 index 0000000..08445af --- /dev/null +++ b/terraform/aws_using_ami/mini_environment/main.tf @@ -0,0 +1,114 @@ +terraform { + backend "http" {} +} + +variable "slug" { + type = "string" +} + +variable "aws_access_key" { + type = "string" +} + +variable "aws_secret_key" { + type = "string" +} + +variable "aws_region" { + type = "string" +} + +variable "aws_route_53_zone_id" { + type = "string" +} + +variable "ami_id" { + type = "string" +} + +variable "backend_remote_state_address" { + type = "string" +} + +variable "backend_remote_state_username" { + type = "string" +} + +variable "backend_remote_state_password" { + type = "string" +} + +variable "ssh_private_key" { + type = "string" +} + +provider "aws" { + access_key = "${var.aws_access_key}" + secret_key = "${var.aws_secret_key}" + region = "${var.aws_region}" +} + + +data "terraform_remote_state" "backend" { + backend = "http" + config { + address = "${var.backend_remote_state_address}" + username = "${var.backend_remote_state_username}" + password = "${var.backend_remote_state_password}" + } +} + +data "aws_route53_zone" "main" { + zone_id = "${var.aws_route_53_zone_id}" +} + + +resource "aws_spot_instance_request" "main" { + ami = "${var.ami_id}" + instance_type = "t2.xlarge" + key_name = "${data.terraform_remote_state.backend.deployer_key_pair_name}" + security_groups = [ + "${data.terraform_remote_state.backend.guix_client_security_group_name}", + "${data.terraform_remote_state.backend.public_webserver_security_group_name}", + "${data.terraform_remote_state.backend.ssh_access_from_mini_environment_admin_security_group_name}" + ] + + wait_for_fulfillment = true + spot_price = "0.21" + spot_type = "one-time" + + root_block_device { + volume_size = "200" + } +} + +resource "aws_route53_record" "main" { + zone_id = "${data.aws_route53_zone.main.zone_id}" + name = "${var.slug}" + type = "A" + ttl = "60" + records = ["${aws_spot_instance_request.main.public_ip}"] +} + +resource "aws_route53_record" "wildcard" { + zone_id = "${data.aws_route53_zone.main.zone_id}" + name = "*.${var.slug}" + type = "A" + ttl = "60" + records = ["${aws_spot_instance_request.main.public_ip}"] +} + +# Outputs + +output "spot_bid_status" { + value = "${aws_spot_instance_request.main.spot_bid_status}" +} + +output "spot_request_status" { + value = "${aws_spot_instance_request.main.spot_request_state}" +} + +output "mini_environment_up" { + value = "${aws_spot_instance_request.main.spot_bid_status == "fulfilled"}" +} + -- cgit v1.2.3