From 7aca7bcc04ae79cc8450f6aaaeee794392075710 Mon Sep 17 00:00:00 2001 From: Manuel Alejandro de Brito Fontes Date: Mon, 30 Sep 2019 18:33:46 -0300 Subject: [PATCH] Terraform release (#4613) * Add script to build the ingress controller image using terraform * Update terraform to 0.12.9 --- build/build-ingress-controller.sh | 52 +++++ build/build-nginx-image.sh | 2 + build/images/ingress-controller/.dockerignore | 1 + build/images/ingress-controller/.gitignore | 7 + build/images/ingress-controller/Dockerfile | 19 ++ .../build-ingress-controller.sh | 93 +++++++++ build/images/ingress-controller/entrypoint.sh | 54 +++++ build/images/ingress-controller/main.tf | 184 ++++++++++++++++++ build/images/ingress-controller/variables.tf | 52 +++++ build/images/ingress-controller/versions.tf | 11 ++ build/images/nginx/Dockerfile | 2 +- 11 files changed, 476 insertions(+), 1 deletion(-) create mode 100755 build/build-ingress-controller.sh create mode 100644 build/images/ingress-controller/.dockerignore create mode 100644 build/images/ingress-controller/.gitignore create mode 100644 build/images/ingress-controller/Dockerfile create mode 100644 build/images/ingress-controller/build-ingress-controller.sh create mode 100755 build/images/ingress-controller/entrypoint.sh create mode 100644 build/images/ingress-controller/main.tf create mode 100644 build/images/ingress-controller/variables.tf create mode 100644 build/images/ingress-controller/versions.tf diff --git a/build/build-ingress-controller.sh b/build/build-ingress-controller.sh new file mode 100755 index 0000000000..fd6769405f --- /dev/null +++ b/build/build-ingress-controller.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if [ -n "$DEBUG" ]; then + set -x +fi + +set -o errexit +set -o nounset +set -o pipefail + +DIR=$(cd $(dirname "${BASH_SOURCE}") && pwd -P) + +AWS_FILE="${DIR}/images/nginx/aws.tfvars" +ENV_FILE="${DIR}/images/nginx/env.tfvars" + +if [ ! -f "${AWS_FILE}" ]; then + echo "File $AWS_FILE does not exist. Please create this file with keys access_key an secret_key" + exit 1 +fi + +if [ ! -f "${ENV_FILE}" ]; then + echo "File $ENV_FILE does not exist. Please create this file with keys docker_username and docker_password" + exit 1 +fi + +# build local terraform image to build nginx +docker build -t build-ingress-controller-terraform $DIR/images/ingress-controller + +# build nginx and publish docker images to quay.io. +# this can take up to two hours. +docker run --rm -it \ + --volume $DIR/images/ingress-controller:/tf \ + -w /tf \ + -v ${AWS_FILE}:/root/aws.tfvars:ro \ + -v ${ENV_FILE}:/root/env.tfvars:ro \ + build-ingress-controller-terraform + +docker rmi -f build-ingress-controller-terraform diff --git a/build/build-nginx-image.sh b/build/build-nginx-image.sh index 7f1324f011..cb9de44ccf 100755 --- a/build/build-nginx-image.sh +++ b/build/build-nginx-image.sh @@ -48,3 +48,5 @@ docker run --rm -it \ -v ${AWS_FILE}:/root/aws.tfvars:ro \ -v ${ENV_FILE}:/root/env.tfvars:ro \ build-nginx-terraform + +docker rmi -f build-nginx-terraform diff --git a/build/images/ingress-controller/.dockerignore b/build/images/ingress-controller/.dockerignore new file mode 100644 index 0000000000..c45cf41694 --- /dev/null +++ b/build/images/ingress-controller/.dockerignore @@ -0,0 +1 @@ +*.tfvars diff --git a/build/images/ingress-controller/.gitignore b/build/images/ingress-controller/.gitignore new file mode 100644 index 0000000000..dfb7ae8c59 --- /dev/null +++ b/build/images/ingress-controller/.gitignore @@ -0,0 +1,7 @@ +.terraform* +terraform* +*.tfstate +*.tfstate.backup +id_rsa* +aws.tfvars +env.tfvars diff --git a/build/images/ingress-controller/Dockerfile b/build/images/ingress-controller/Dockerfile new file mode 100644 index 0000000000..1cb670e78b --- /dev/null +++ b/build/images/ingress-controller/Dockerfile @@ -0,0 +1,19 @@ +FROM quay.io/kubernetes-ingress-controller/debian-base-amd64:0.1 + +ENV TERRAFORM_VERSION 0.12.9 + +RUN clean-install \ + bash \ + curl \ + ca-certificates \ + unzip \ + git \ + openssh-client + +RUN curl -sSL -o /terraform.zip "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" \ + && unzip /terraform.zip -d /usr/bin \ + && rm -rf /terraform.zip + +COPY entrypoint.sh / + +CMD [ "/entrypoint.sh" ] diff --git a/build/images/ingress-controller/build-ingress-controller.sh b/build/images/ingress-controller/build-ingress-controller.sh new file mode 100644 index 0000000000..adc061c6d6 --- /dev/null +++ b/build/images/ingress-controller/build-ingress-controller.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +function source_tfvars() { + eval "$( + awk 'BEGIN {FS=OFS="="} + !/^(#| *$)/ && /^.+=.+$/ { + gsub(/^[ \t]+|[ \t]+$/, "", $1); + gsub(/\./, "_", $1); + gsub(/^[ \t]+|[ \t]+$/, "", $2); + if ($1 && $2) print $0 + }' "$@" + )" +} + +source_tfvars /tmp/env + +export DEBIAN_FRONTEND=noninteractive + +apt -q=3 update + +apt -q=3 dist-upgrade --yes + +add-apt-repository universe --yes +add-apt-repository multiverse --yes + +apt -q=3 update + +apt -q=3 install \ + apt-transport-https \ + ca-certificates \ + curl \ + make \ + htop \ + software-properties-common --yes + +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - + +add-apt-repository \ + "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ + $(lsb_release -cs) \ + stable" --yes + +apt -q=3 update + +apt -q=3 install docker-ce --yes + +echo ${docker_password} | docker login -u ${docker_username} --password-stdin quay.io + +curl -sL -o /usr/local/bin/gimme https://raw.githubusercontent.com/travis-ci/gimme/master/gimme +chmod +x /usr/local/bin/gimme + +eval "$(gimme 1.13.1)" + +export GOPATH="/tmp/go" + +INGRESS_DIRECTORY="${GOPATH}/src/k8s.io" + +mkdir -p ${INGRESS_DIRECTORY} +cd ${INGRESS_DIRECTORY} + +git clone https://github.com/kubernetes/ingress-nginx + +cd ingress-nginx + +make register-qemu + +echo "Building NGINX image..." +make all-container + +echo "Publishing NGINX images..." +make all-push + +# Requires https://github.com/kubernetes/ingress-nginx/pull/4271 +#echo "Creating multi-arch images..." +#make push-manifest diff --git a/build/images/ingress-controller/entrypoint.sh b/build/images/ingress-controller/entrypoint.sh new file mode 100755 index 0000000000..9170134d08 --- /dev/null +++ b/build/images/ingress-controller/entrypoint.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +catch() { + if [ "$1" == "0" ]; then + exit 0 + fi + + echo "Error $1 occurred on $2" + + echo "Removing temporal resources..." + terraform destroy -auto-approve \ + -var-file /root/aws.tfvars \ + -var-file /root/env.tfvars \ + -var valid_until="${EC2_VALID_UNTIL}" +} +trap 'catch $? $LINENO' ERR + +terraform init + +# destroy spot instance after two hours +EC2_VALID_UNTIL=$(date -d "+2 hours" +%Y-%m-%dT%H:%M:%SZ) + +terraform plan \ + -var-file /root/aws.tfvars \ + -var-file /root/env.tfvars \ + -var valid_until="${EC2_VALID_UNTIL}" + +terraform apply -auto-approve \ + -var-file /root/aws.tfvars \ + -var-file /root/env.tfvars \ + -var valid_until="${EC2_VALID_UNTIL}" + +terraform destroy -auto-approve \ + -var-file /root/aws.tfvars \ + -var-file /root/env.tfvars \ + -var valid_until="${EC2_VALID_UNTIL}" diff --git a/build/images/ingress-controller/main.tf b/build/images/ingress-controller/main.tf new file mode 100644 index 0000000000..ab585f8442 --- /dev/null +++ b/build/images/ingress-controller/main.tf @@ -0,0 +1,184 @@ +terraform { + backend "local" { + path = "terraform.tfstate" + } +} + +provider "aws" { + access_key = var.access_key + secret_key = var.secret_key + region = var.region +} + +resource "aws_vpc" "vpc" { + cidr_block = var.cidr_vpc + enable_dns_support = true + enable_dns_hostnames = true + tags = { + "Project" = var.project_tag + } +} + +resource "aws_internet_gateway" "igw" { + vpc_id = aws_vpc.vpc.id + tags = { + "Project" = var.project_tag + } +} + +resource "aws_subnet" "subnet_public" { + vpc_id = aws_vpc.vpc.id + cidr_block = var.cidr_subnet + map_public_ip_on_launch = "true" + availability_zone = var.availability_zone + tags = { + "Project" = var.project_tag + } +} + +resource "aws_route_table" "rtb_public" { + vpc_id = aws_vpc.vpc.id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.igw.id + } + + tags = { + "Project" = var.project_tag + } +} + +resource "aws_route_table_association" "rta_subnet_public" { + subnet_id = aws_subnet.subnet_public.id + route_table_id = aws_route_table.rtb_public.id +} + +resource "aws_security_group" "allow_ssh" { + name = "ssh" + vpc_id = aws_vpc.vpc.id + + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = { + "Project" = var.project_tag + } +} + +resource "tls_private_key" "bootstrap_private_key" { + algorithm = "RSA" + rsa_bits = "4096" +} + +resource "aws_key_pair" "ssh_key" { + key_name = "ssh-key_${var.project_tag}" + public_key = chomp(tls_private_key.bootstrap_private_key.public_key_openssh) +} + +resource "local_file" "public_key_openssh" { + count = 1 + depends_on = [tls_private_key.bootstrap_private_key] + content = tls_private_key.bootstrap_private_key.public_key_pem + filename = "id_rsa.pub" +} + +resource "local_file" "private_key_openssh" { + count = 1 + depends_on = [tls_private_key.bootstrap_private_key] + content = tls_private_key.bootstrap_private_key.private_key_pem + filename = "id_rsa" +} + +data "aws_ami" "latest-ubuntu" { + most_recent = true + + owners = ["099720109477"] + + filter { + name = "name" + values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } + + filter { + name = "root-device-type" + values = ["ebs"] + } + + filter { + name = "block-device-mapping.volume-type" + values = ["gp2"] + } +} + +resource "aws_spot_instance_request" "build_worker" { + ami = data.aws_ami.latest-ubuntu.id + instance_type = var.instance_type + subnet_id = aws_subnet.subnet_public.id + vpc_security_group_ids = [aws_security_group.allow_ssh.id] + + valid_until = var.valid_until + + key_name = aws_key_pair.ssh_key.key_name + + spot_price = "2" + spot_type = "one-time" + + ebs_optimized = true + + root_block_device { + volume_size = 32 + volume_type = "gp2" + delete_on_termination = true + } + + wait_for_fulfillment = true + instance_initiated_shutdown_behavior = "terminate" + + associate_public_ip_address = true + + tags = { + "Project" = var.project_tag + } + + connection { + host = coalesce(self.public_ip, self.private_ip) + type = "ssh" + user = "ubuntu" + private_key = tls_private_key.bootstrap_private_key.private_key_pem + } + + provisioner "file" { + source = "build-ingress-controller.sh" + destination = "/tmp/build-ingress-controller.sh" + } + + provisioner "file" { + source = "/root/env.tfvars" + destination = "/tmp/env" + } + + provisioner "remote-exec" { + inline = [ + "echo Building ingress controller images...", + "chmod +x /tmp/build-ingress-controller.sh", + "sudo /tmp/build-ingress-controller.sh", + ] + } +} diff --git a/build/images/ingress-controller/variables.tf b/build/images/ingress-controller/variables.tf new file mode 100644 index 0000000000..48b0935d0c --- /dev/null +++ b/build/images/ingress-controller/variables.tf @@ -0,0 +1,52 @@ +variable "access_key" { +} + +variable "secret_key" { +} + +variable "valid_until" { +} + +variable "docker_username" { +} + +variable "docker_password" { +} + +variable "region" { + default = "us-west-2" +} + +variable "cidr_vpc" { + description = "CIDR block for the VPC" + default = "10.4.0.0/16" +} + +variable "cidr_subnet" { + description = "CIDR block for the subnet" + default = "10.4.0.0/24" +} + +variable "availability_zone" { + description = "availability zone to create subnet" + default = "us-west-2b" +} + +variable "ssh_key_path" { + description = "Path to the SSH key" + default = "~/.ssh/id_rsa" +} + +variable "ssh_public_key_path" { + description = "Path to the public SSH key" + default = "~/.ssh/id_rsa.pub" +} + +variable "instance_type" { + description = "EC2 instance" + default = "c5.18xlarge" +} + +variable "project_tag" { + default = "kubernetes/ingress-nginx" +} diff --git a/build/images/ingress-controller/versions.tf b/build/images/ingress-controller/versions.tf new file mode 100644 index 0000000000..b5518687a9 --- /dev/null +++ b/build/images/ingress-controller/versions.tf @@ -0,0 +1,11 @@ + +terraform { + required_version = ">= 0.12" + + required_providers { + aws = "~> 2.0" + tls = "~> 2.0" + local = "~> 1.3" + null = "~> 2.1" + } +} diff --git a/build/images/nginx/Dockerfile b/build/images/nginx/Dockerfile index a075db0d35..1cb670e78b 100644 --- a/build/images/nginx/Dockerfile +++ b/build/images/nginx/Dockerfile @@ -1,6 +1,6 @@ FROM quay.io/kubernetes-ingress-controller/debian-base-amd64:0.1 -ENV TERRAFORM_VERSION 0.12.6 +ENV TERRAFORM_VERSION 0.12.9 RUN clean-install \ bash \