e2e: split Packer build scripts from TF provisioning (#6542)

Make a clear split between Packer and Terraform provisioning steps:
the scripts in the `packer/linux` directory are run when we build the
AMI whereas the stuff in shared are run at Terraform provisioning time.

Merging all runtime provisioning scripts into a single script for each
of server/client solves the following:

* Userdata scripts can't take arguments, they can only be templated
  and that means we have to do TF escaping in bash/powershell scripts.
* TF provisioning scripts race with userdata scripts.
This commit is contained in:
Tim Gross 2019-10-25 08:08:24 -04:00 committed by GitHub
parent 3c1b48e9d9
commit efbd680d4e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 219 additions and 215 deletions

View file

@ -1,31 +1,3 @@
data "template_file" "user_data_server" {
template = file("${path.root}/user-data-server.sh")
vars = {
server_count = var.server_count
region = var.region
retry_join = var.retry_join
}
}
data "template_file" "user_data_client" {
template = file("${path.root}/user-data-client.sh")
count = var.client_count
vars = {
region = var.region
retry_join = var.retry_join
}
}
data "template_file" "nomad_client_config" {
template = file("${path.root}/configs/client.hcl")
}
data "template_file" "nomad_server_config" {
template = "}"
}
resource "aws_instance" "server" {
ami = data.aws_ami.main.image_id
instance_type = var.instance_type
@ -41,9 +13,21 @@ resource "aws_instance" "server" {
User = data.aws_caller_identity.current.arn
}
user_data = data.template_file.user_data_server.rendered
iam_instance_profile = aws_iam_instance_profile.instance_profile.name
# copy up all provisioning scripts and configs
provisioner "file" {
source = "shared/"
destination = "/ops/shared"
connection {
host = coalesce(self.public_ip, self.private_ip)
type = "ssh"
user = "ubuntu"
private_key = module.keys.private_key_pem
}
}
provisioner "file" {
content = file(
"${path.root}/configs/${var.indexed == false ? "server.hcl" : "indexed/server-${count.index}.hcl"}",
@ -57,9 +41,11 @@ resource "aws_instance" "server" {
private_key = module.keys.private_key_pem
}
}
provisioner "remote-exec" {
inline = [
"/ops/shared/config/provision-server.sh ${var.nomad_sha}",
"chmod +x /ops/shared/config/provision-server.sh",
"/ops/shared/config/provision-server.sh aws ${var.server_count} '${var.retry_join}' ${var.nomad_sha}",
]
connection {
@ -94,9 +80,21 @@ resource "aws_instance" "client" {
delete_on_termination = "true"
}
user_data = element(data.template_file.user_data_client.*.rendered, count.index)
iam_instance_profile = aws_iam_instance_profile.instance_profile.name
# copy up all provisioning scripts and configs
provisioner "file" {
source = "shared/"
destination = "/ops/shared"
connection {
host = coalesce(self.public_ip, self.private_ip)
type = "ssh"
user = "ubuntu"
private_key = module.keys.private_key_pem
}
}
provisioner "file" {
content = file(
"${path.root}/configs/${var.indexed == false ? "client.hcl" : "indexed/client-${count.index}.hcl"}",
@ -113,7 +111,8 @@ resource "aws_instance" "client" {
provisioner "remote-exec" {
inline = [
"/ops/shared/config/provision-client.sh ${var.nomad_sha}",
"chmod +x /ops/shared/config/provision-client.sh",
"/ops/shared/config/provision-client.sh aws '${var.retry_join}' ${var.nomad_sha}",
]
connection {
@ -124,4 +123,3 @@ resource "aws_instance" "client" {
}
}
}

View file

@ -1,31 +0,0 @@
{
"builders": [{
"type": "amazon-ebs",
"region": "us-east-1",
"source_ami": "ami-80861296",
"instance_type": "t2.medium",
"ssh_username": "ubuntu",
"ami_name": "nomad-e2e-{{timestamp}}",
"ami_groups": ["all"],
"tags": {
"OS": "Ubuntu"
}
}],
"provisioners": [
{
"type": "shell",
"inline": [
"sudo mkdir /ops",
"sudo chmod 777 /ops"
]
},
{
"type": "file",
"source": "shared",
"destination": "/ops"
},
{
"type": "shell",
"script": "shared/scripts/setup.sh"
}]
}

View file

@ -0,0 +1,21 @@
# Packer Builds
These builds are run as-needed to update the AMIs used by the end-to-end test infrastructure.
## What goes here?
* steps that aren't specific to a given Nomad build: ex. all Linux instances need `jq` and `awscli`.
* steps that aren't specific to a given EC2 instance: nothing that includes an IP address.
* steps that infrequently change: the version of Consul or Vault we ship.
## Running Packer builds
```sh
$ packer --version
1.4.4
# build linux AMI
$ packer build packer.json
```

View file

@ -5,9 +5,10 @@ set -e
# Disable interactive apt prompts
export DEBIAN_FRONTEND=noninteractive
cd /ops
sudo mkdir -p /ops/shared
sudo chown -R ubuntu:ubuntu /ops/shared
CONFIGDIR=/ops/shared/config
cd /ops
CONSULVERSION=1.6.0
CONSULDOWNLOAD=https://releases.hashicorp.com/consul/${CONSULVERSION}/consul_${CONSULVERSION}_linux_amd64.zip
@ -42,8 +43,8 @@ sudo pip install numpy
sudo ufw disable || echo "ufw not installed"
echo "Install Consul"
curl -L $CONSULDOWNLOAD > consul.zip
sudo unzip consul.zip -d /usr/local/bin
curl -L -o /tmp/consul.zip $CONSULDOWNLOAD
sudo unzip /tmp/consul.zip -d /usr/local/bin
sudo chmod 0755 /usr/local/bin/consul
sudo chown root:root /usr/local/bin/consul
@ -54,8 +55,8 @@ sudo mkdir -p $CONSULDIR
sudo chmod 755 $CONSULDIR
echo "Install Vault"
curl -L $VAULTDOWNLOAD > vault.zip
sudo unzip vault.zip -d /usr/local/bin
curl -L -o /tmp/vault.zip $VAULTDOWNLOAD
sudo unzip /tmp/vault.zip -d /usr/local/bin
sudo chmod 0755 /usr/local/bin/vault
sudo chown root:root /usr/local/bin/vault
@ -66,8 +67,8 @@ sudo mkdir -p $VAULTDIR
sudo chmod 755 $VAULTDIR
echo "Install Nomad"
curl -L $NOMADDOWNLOAD > nomad.zip
sudo unzip nomad.zip -d /usr/local/bin
curl -L -o /tmp/nomad.zip $NOMADDOWNLOAD
sudo unzip /tmp/nomad.zip -d /usr/local/bin
sudo chmod 0755 /usr/local/bin/nomad
sudo chown root:root /usr/local/bin/nomad

View file

@ -0,0 +1,24 @@
{
"builders": [
{
"type": "amazon-ebs",
"region": "us-east-1",
"source_ami": "ami-80861296",
"instance_type": "t2.medium",
"ssh_username": "ubuntu",
"ami_name": "nomad-e2e-{{timestamp}}",
"ami_groups": [
"all"
],
"tags": {
"OS": "Ubuntu"
}
}
],
"provisioners": [
{
"type": "shell",
"script": "./linux/setup.sh"
}
]
}

View file

@ -0,0 +1,10 @@
# Terraform Provisioning
These scripts are copied up to instances via Terraform provisioning and executed after launch. This allows us to update the Nomad configurations for features that land on master without having to re-bake AMIs.
## What goes here?
* steps that are specific to a given Nomad build: ex. all Nomad configuration files.
* steps that are specific to a given EC2 instance: configuring IP addresses.
These scripts *should* be idempotent: copy configurations from `/ops/shared` to their destinations where the services expect them to be, rather than moving them.

View file

@ -3,7 +3,60 @@
set -o errexit
set -o nounset
nomad_sha=$1
CONFIGDIR=/ops/shared/config
CONSULCONFIGDIR=/etc/consul.d
NOMADCONFIGDIR=/etc/nomad.d
HADOOP_VERSION=hadoop-2.7.7
HADOOPCONFIGDIR=/usr/local/$HADOOP_VERSION/etc/hadoop
HOME_DIR=ubuntu
# Wait for network
sleep 15
# IP_ADDRESS=$(curl http://instance-data/latest/meta-data/local-ipv4)
IP_ADDRESS="$(/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}')"
DOCKER_BRIDGE_IP_ADDRESS=(`ifconfig docker0 2>/dev/null|awk '/inet addr:/ {print $2}'|sed 's/addr://'`)
CLOUD="$1"
RETRY_JOIN="$2"
nomad_sha="$3"
# Consul
sed -i "s/IP_ADDRESS/$IP_ADDRESS/g" $CONFIGDIR/consul_client.json
sed -i "s/RETRY_JOIN/$RETRY_JOIN/g" $CONFIGDIR/consul_client.json
sudo cp $CONFIGDIR/consul_client.json $CONSULCONFIGDIR/consul.json
sudo cp $CONFIGDIR/consul_$CLOUD.service /etc/systemd/system/consul.service
sudo systemctl enable consul.service
sudo systemctl start consul.service
sleep 10
export NOMAD_ADDR=http://$IP_ADDRESS:4646
# Add hostname to /etc/hosts
echo "127.0.0.1 $(hostname)" | sudo tee --append /etc/hosts
# Add Docker bridge network IP to /etc/resolv.conf (at the top)
echo "nameserver $DOCKER_BRIDGE_IP_ADDRESS" | sudo tee /etc/resolv.conf.new
cat /etc/resolv.conf | sudo tee --append /etc/resolv.conf.new
sudo mv /etc/resolv.conf.new /etc/resolv.conf
# Hadoop config file to enable HDFS CLI
sudo cp $CONFIGDIR/core-site.xml $HADOOPCONFIGDIR
# Move examples directory to $HOME
sudo mv /ops/examples /home/$HOME_DIR
sudo chown -R $HOME_DIR:$HOME_DIR /home/$HOME_DIR/examples
sudo chmod -R 775 /home/$HOME_DIR/examples
# Set env vars for tool CLIs
echo "export VAULT_ADDR=http://$IP_ADDRESS:8200" | sudo tee --append /home/$HOME_DIR/.bashrc
echo "export NOMAD_ADDR=http://$IP_ADDRESS:4646" | sudo tee --append /home/$HOME_DIR/.bashrc
echo "export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre" | sudo tee --append /home/$HOME_DIR/.bashrc
# Update PATH
echo "export PATH=$PATH:/usr/local/bin/spark/bin:/usr/local/$HADOOP_VERSION/bin" | sudo tee --append /home/$HOME_DIR/.bashrc
# download
aws s3 cp s3://nomad-team-test-binary/builds-oss/${nomad_sha}.tar.gz nomad.tar.gz

View file

@ -3,7 +3,76 @@
set -o errexit
set -o nounset
nomad_sha=$1
CONFIGDIR=/ops/shared/config
CONSULCONFIGDIR=/etc/consul.d
VAULTCONFIGDIR=/etc/vault.d
NOMADCONFIGDIR=/etc/nomad.d
HADOOP_VERSION=hadoop-2.7.7
HADOOPCONFIGDIR=/usr/local/$HADOOP_VERSION/etc/hadoop
HOME_DIR=ubuntu
# Wait for network
sleep 15
# IP_ADDRESS=$(curl http://instance-data/latest/meta-data/local-ipv4)
IP_ADDRESS="$(/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}')"
DOCKER_BRIDGE_IP_ADDRESS=(`ifconfig docker0 2>/dev/null|awk '/inet addr:/ {print $2}'|sed 's/addr://'`)
CLOUD="$1"
SERVER_COUNT="$2"
RETRY_JOIN="$3"
nomad_sha="$4"
# Consul
sed -i "s/IP_ADDRESS/$IP_ADDRESS/g" $CONFIGDIR/consul.json
sed -i "s/SERVER_COUNT/$SERVER_COUNT/g" $CONFIGDIR/consul.json
sed -i "s/RETRY_JOIN/$RETRY_JOIN/g" $CONFIGDIR/consul.json
sudo cp $CONFIGDIR/consul.json $CONSULCONFIGDIR
sudo cp $CONFIGDIR/consul_$CLOUD.service /etc/systemd/system/consul.service
sudo systemctl enable consul.service
sudo systemctl start consul.service
sleep 10
export CONSUL_HTTP_ADDR=$IP_ADDRESS:8500
export CONSUL_RPC_ADDR=$IP_ADDRESS:8400
# Vault
sed -i "s/IP_ADDRESS/$IP_ADDRESS/g" $CONFIGDIR/vault.hcl
sudo cp $CONFIGDIR/vault.hcl $VAULTCONFIGDIR
sudo cp $CONFIGDIR/vault.service /etc/systemd/system/vault.service
sudo systemctl enable vault.service
sudo systemctl start vault.service
export NOMAD_ADDR=http://$IP_ADDRESS:4646
# Add hostname to /etc/hosts
echo "127.0.0.1 $(hostname)" | sudo tee --append /etc/hosts
# Add Docker bridge network IP to /etc/resolv.conf (at the top)
echo "nameserver $DOCKER_BRIDGE_IP_ADDRESS" | sudo tee /etc/resolv.conf.new
cat /etc/resolv.conf | sudo tee --append /etc/resolv.conf.new
sudo mv /etc/resolv.conf.new /etc/resolv.conf
# Hadoop
sudo cp $CONFIGDIR/core-site.xml $HADOOPCONFIGDIR
# Move examples directory to $HOME
sudo mv /ops/examples /home/$HOME_DIR
sudo chown -R $HOME_DIR:$HOME_DIR /home/$HOME_DIR/examples
sudo chmod -R 775 /home/$HOME_DIR/examples
# Set env vars for tool CLIs
echo "export CONSUL_RPC_ADDR=$IP_ADDRESS:8400" | sudo tee --append /home/$HOME_DIR/.bashrc
echo "export CONSUL_HTTP_ADDR=$IP_ADDRESS:8500" | sudo tee --append /home/$HOME_DIR/.bashrc
echo "export VAULT_ADDR=http://$IP_ADDRESS:8200" | sudo tee --append /home/$HOME_DIR/.bashrc
echo "export NOMAD_ADDR=http://$IP_ADDRESS:4646" | sudo tee --append /home/$HOME_DIR/.bashrc
echo "export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre" | sudo tee --append /home/$HOME_DIR/.bashrc
# Update PATH
echo "export PATH=$PATH:/usr/local/bin/spark/bin:/usr/local/$HADOOP_VERSION/bin" | sudo tee --append /home/$HOME_DIR/.bashrc
# download
aws s3 cp s3://nomad-team-test-binary/builds-oss/${nomad_sha}.tar.gz nomad.tar.gz

View file

@ -1 +0,0 @@
Scripts used by Packer to create base images

View file

@ -1,56 +0,0 @@
#!/bin/bash
set -e
CONFIGDIR=/ops/shared/config
CONSULCONFIGDIR=/etc/consul.d
NOMADCONFIGDIR=/etc/nomad.d
HADOOP_VERSION=hadoop-2.7.6
HADOOPCONFIGDIR=/usr/local/$HADOOP_VERSION/etc/hadoop
HOME_DIR=ubuntu
# Wait for network
sleep 15
# IP_ADDRESS=$(curl http://instance-data/latest/meta-data/local-ipv4)
IP_ADDRESS="$(/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}')"
DOCKER_BRIDGE_IP_ADDRESS=(`ifconfig docker0 2>/dev/null|awk '/inet addr:/ {print $2}'|sed 's/addr://'`)
CLOUD=$1
RETRY_JOIN=$2
# Consul
sed -i "s/IP_ADDRESS/$IP_ADDRESS/g" $CONFIGDIR/consul_client.json
sed -i "s/RETRY_JOIN/$RETRY_JOIN/g" $CONFIGDIR/consul_client.json
sudo cp $CONFIGDIR/consul_client.json $CONSULCONFIGDIR/consul.json
sudo cp $CONFIGDIR/consul_$CLOUD.service /etc/systemd/system/consul.service
sudo systemctl enable consul.service
sudo systemctl start consul.service
sleep 10
export NOMAD_ADDR=http://$IP_ADDRESS:4646
# Add hostname to /etc/hosts
echo "127.0.0.1 $(hostname)" | sudo tee --append /etc/hosts
# Add Docker bridge network IP to /etc/resolv.conf (at the top)
echo "nameserver $DOCKER_BRIDGE_IP_ADDRESS" | sudo tee /etc/resolv.conf.new
cat /etc/resolv.conf | sudo tee --append /etc/resolv.conf.new
sudo mv /etc/resolv.conf.new /etc/resolv.conf
# Hadoop config file to enable HDFS CLI
sudo cp $CONFIGDIR/core-site.xml $HADOOPCONFIGDIR
# Move examples directory to $HOME
sudo mv /ops/examples /home/$HOME_DIR
sudo chown -R $HOME_DIR:$HOME_DIR /home/$HOME_DIR/examples
sudo chmod -R 775 /home/$HOME_DIR/examples
# Set env vars for tool CLIs
echo "export VAULT_ADDR=http://$IP_ADDRESS:8200" | sudo tee --append /home/$HOME_DIR/.bashrc
echo "export NOMAD_ADDR=http://$IP_ADDRESS:4646" | sudo tee --append /home/$HOME_DIR/.bashrc
echo "export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre" | sudo tee --append /home/$HOME_DIR/.bashrc
# Update PATH
echo "export PATH=$PATH:/usr/local/bin/spark/bin:/usr/local/$HADOOP_VERSION/bin" | sudo tee --append /home/$HOME_DIR/.bashrc

View file

@ -1,72 +0,0 @@
#!/bin/bash
set -e
CONFIGDIR=/ops/shared/config
CONSULCONFIGDIR=/etc/consul.d
VAULTCONFIGDIR=/etc/vault.d
NOMADCONFIGDIR=/etc/nomad.d
HADOOP_VERSION=hadoop-2.7.6
HADOOPCONFIGDIR=/usr/local/$HADOOP_VERSION/etc/hadoop
HOME_DIR=ubuntu
# Wait for network
sleep 15
# IP_ADDRESS=$(curl http://instance-data/latest/meta-data/local-ipv4)
IP_ADDRESS="$(/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}')"
DOCKER_BRIDGE_IP_ADDRESS=(`ifconfig docker0 2>/dev/null|awk '/inet addr:/ {print $2}'|sed 's/addr://'`)
CLOUD=$1
SERVER_COUNT=$2
RETRY_JOIN=$3
# Consul
sed -i "s/IP_ADDRESS/$IP_ADDRESS/g" $CONFIGDIR/consul.json
sed -i "s/SERVER_COUNT/$SERVER_COUNT/g" $CONFIGDIR/consul.json
sed -i "s/RETRY_JOIN/$RETRY_JOIN/g" $CONFIGDIR/consul.json
sudo cp $CONFIGDIR/consul.json $CONSULCONFIGDIR
sudo cp $CONFIGDIR/consul_$CLOUD.service /etc/systemd/system/consul.service
sudo systemctl enable consul.service
sudo systemctl start consul.service
sleep 10
export CONSUL_HTTP_ADDR=$IP_ADDRESS:8500
export CONSUL_RPC_ADDR=$IP_ADDRESS:8400
# Vault
sed -i "s/IP_ADDRESS/$IP_ADDRESS/g" $CONFIGDIR/vault.hcl
sudo cp $CONFIGDIR/vault.hcl $VAULTCONFIGDIR
sudo cp $CONFIGDIR/vault.service /etc/systemd/system/vault.service
sudo systemctl enable vault.service
sudo systemctl start vault.service
export NOMAD_ADDR=http://$IP_ADDRESS:4646
# Add hostname to /etc/hosts
echo "127.0.0.1 $(hostname)" | sudo tee --append /etc/hosts
# Add Docker bridge network IP to /etc/resolv.conf (at the top)
echo "nameserver $DOCKER_BRIDGE_IP_ADDRESS" | sudo tee /etc/resolv.conf.new
cat /etc/resolv.conf | sudo tee --append /etc/resolv.conf.new
sudo mv /etc/resolv.conf.new /etc/resolv.conf
# Hadoop
sudo cp $CONFIGDIR/core-site.xml $HADOOPCONFIGDIR
# Move examples directory to $HOME
sudo mv /ops/examples /home/$HOME_DIR
sudo chown -R $HOME_DIR:$HOME_DIR /home/$HOME_DIR/examples
sudo chmod -R 775 /home/$HOME_DIR/examples
# Set env vars for tool CLIs
echo "export CONSUL_RPC_ADDR=$IP_ADDRESS:8400" | sudo tee --append /home/$HOME_DIR/.bashrc
echo "export CONSUL_HTTP_ADDR=$IP_ADDRESS:8500" | sudo tee --append /home/$HOME_DIR/.bashrc
echo "export VAULT_ADDR=http://$IP_ADDRESS:8200" | sudo tee --append /home/$HOME_DIR/.bashrc
echo "export NOMAD_ADDR=http://$IP_ADDRESS:4646" | sudo tee --append /home/$HOME_DIR/.bashrc
echo "export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre" | sudo tee --append /home/$HOME_DIR/.bashrc
# Update PATH
echo "export PATH=$PATH:/usr/local/bin/spark/bin:/usr/local/$HADOOP_VERSION/bin" | sudo tee --append /home/$HOME_DIR/.bashrc

View file

@ -1,6 +0,0 @@
#!/bin/bash
set -e
exec > >(sudo tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
sudo bash /ops/shared/scripts/client.sh "aws" "${retry_join}"

View file

@ -1,6 +0,0 @@
#!/bin/bash
set -e
exec > >(sudo tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
sudo bash /ops/shared/scripts/server.sh "aws" "${server_count}" "${retry_join}"