Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hardware deployment via Terraform #36

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
*.dll
*.exe
.DS_Store
example.tf
terraform.tfplan
terraform.tfstate
bin/
modules-dev/
pkg/
vendor/
website/.vagrant
website/build
website/node_modules
.vagrant/
*.backup
./*.tfstate
.terraform/
*.log
*.bak
*~
.*.swp
.idea
67 changes: 66 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,69 @@
packet-ci-cloud
===============

CI/CD Deployment of Packet nodepool cloud
CI/CD Deployment of Packet Nodepool Cloud

## Prerequisites

### Packet Project ID & API Key

This deployment requires a Packet account for the provisioned bare metal. You'll need your "Packet Project ID" and your "Packet API Key" to proceed. You can use an existing project or create a new project for the deployment.

We recommend setting the Packet API Token and Project ID as environment variables since this prevents tokens from being included in source code files. These values can also be stored within a variables file later if using environment variables isn't desired.
```bash
export TF_VAR_packet_project_id=YOUR_PROJECT_ID_HERE
export TF_VAR_packet_auth_token=YOUR_PACKET_TOKEN_HERE
```

#### Where is my Packet Project ID?

You can find your Project ID under the 'Manage' section in the Packet Portal. They are listed underneath each project in the listing. You can also find the project ID on the project 'Settings' tab, which also features a very handy "copy to clipboard" piece of functionality, for the clicky among us.

#### How can I create a Packet API Key?

You will find your API Key on the left side of the portal. If you have existing keys you will find them listed on that page. If you haven't created one yet, you can click here:

https://app.packet.net/portal#/api-keys/new

### Terraform

These instructions use Terraform from Hashicorp to drive the deployment. If you don't have Terraform installed already, you can download and install Terraform using the instructions on the link below:
https://www.terraform.io/downloads.html

## Deployment Prep

Download this repo from GitHub into a local directory.

```bash
git clone <repo_url>
cd <repo>
cd terraform
```

Update with the keys to access the physical hosts. Terraform will configure the root user on the new hosts with this key
```
cp ~/.ssh/id_rsa.pub .
```

Download the Terraform providers required:
```bash
cd terraform
terraform init
```

Run the Terraform
```bash
terraform plan
terraform apply
```
## Ansible Configuration

Terraform will build a starting in terraform/openstack_user_config.yml using the host information (IP addressing) assigned for the new hosts.

```bash
cp terraform/openstack_user_config.yml .
vi openstack_user_config.yml
```

### Run the Ansible Playbook

97 changes: 97 additions & 0 deletions terraform/BareMetal.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
resource "packet_device" "compute" {

count = "${var.compute_count}"
hostname = "${format("compute-%02d", count.index)}"
operating_system = "${var.operating_system}"
plan = "${var.compute_type}"
tags = ["openstack-${random_id.cloud.hex}"]


connection {
user = "root"
private_key = "${file("${var.cloud_ssh_key_path}")}"
}
user_data = "#cloud-config\n\nssh_authorized_keys:\n - \"${file("${var.cloud_ssh_public_key_path}")}\""
facility = "${var.packet_facility}"
project_id = "${var.packet_project_id}"
billing_cycle = "hourly"

public_ipv4_subnet_size = "31"

connection {
private_key = "${file("${var.cloud_ssh_key_path}")}"
}

provisioner "file" {
source = "${var.operating_system}-${var.control_type}.sh"
destination = "hardware-setup.sh"
}

provisioner "file" {
source = "${var.operating_system}.sh"
destination = "os-setup.sh"
}

provisioner "remote-exec" {
inline = [
"bash os-setup.sh > os-setup.out",
"bash hardware-setup.sh > hardware-setup.out",
"reboot &"
]
}
}

resource "packet_device" "control" {

count = "${var.control_count}"
hostname = "${format("control-%02d", count.index)}"
operating_system = "${var.operating_system}"
plan = "${var.control_type}"
tags = ["openstack-${random_id.cloud.hex}"]

connection {
user = "root"
private_key = "${file("${var.cloud_ssh_key_path}")}"
}
user_data = "#cloud-config\n\nssh_authorized_keys:\n - \"${file("${var.cloud_ssh_public_key_path}")}\""
facility = "${var.packet_facility}"
project_id = "${var.packet_project_id}"
billing_cycle = "hourly"

# enable if elastic IPv4 addresses are required
# public_ipv4_subnet_size = "29"

connection {
private_key = "${file("${var.cloud_ssh_key_path}")}"
}

provisioner "file" {
source = "${var.operating_system}-${var.control_type}.sh"
destination = "hardware-setup.sh"
}

provisioner "file" {
source = "${var.operating_system}.sh"
destination = "os-setup.sh"
}

provisioner "file" {
source = "deployment_host.sh"
destination = "deployment_host.sh"
}

# private SSH key for OSA to use
provisioner "file" {
source = "${var.cloud_ssh_key_path}"
destination = "osa_rsa"
}

provisioner "remote-exec" {
inline = [
"bash os-setup.sh > os-setup.out",
"bash hardware-setup.sh > hardware-setup.out",
"bash deployment_host.sh > deployment_host.out",
"reboot &"
]
}
}
3 changes: 3 additions & 0 deletions terraform/Cloud.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
resource "random_id" "cloud" {
byte_length = 4
}
12 changes: 12 additions & 0 deletions terraform/ContainerSubnet.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
data "packet_precreated_ip_block" "private_block" {
facility = "${var.packet_facility}"
project_id = "${var.packet_project_id}"
address_family = 4
public = false
}

# assigned a /25 by default so we'll add one bit and get a /26
resource "packet_ip_attachment" "container_ip_block" {
device_id = "${packet_device.control.0.id}"
cidr_notation = "${cidrsubnet(data.packet_precreated_ip_block.private_block.cidr_notation,1,1)}"
}
3 changes: 3 additions & 0 deletions terraform/Provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
provider "packet" {
auth_token = "${var.packet_auth_token}"
}
4 changes: 4 additions & 0 deletions terraform/authorized_keys
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6d3lJdnWzH8l4Pf55TeTfAy/3GUaI0BYdwZljpNaX/L5hVvOWVPaUIBuxuTylf5MBxAuotv8ZxGFkUaWTXJaLzRUZ8l5d8jztdft58v4rHcTthdTafKC50JPw+WBhHgWLRxddvcxW/ou6R5X9VLKZ/wCwTCwQgZEecf5s3xXQjvFN2urI8nrauVMLypDfl0hwaPylf0FBfTApdscAFQY+RAvPU1Sb1Mp2UVzB3+bblGHNa5IE/OJDujnisEDAM1hbkyyRWQWzh7yXqML9G5LNF0E5KYAioAgUjmPKnik4B/aXQhDEip0mVpuhM8iPvOVGW+z65Q89hq1sIbLJnVRd studarus@shell
ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAoc+BHLERUqmw9dvR0H+36lAEs4SHzO0Eadx2xiqavhrYyJGWe0AxmLs2upRjEUtuOP22uaTW0QE7Fb31KygiN96jgac219zTsedKvcq/vAnNvHYCi2I07+yg9T5Lk/FOPzRzGLR+sSnqFnw+Hgz75JDmtSOxCJODhFTMFG9cHRfjq3Cu1cImed1SkLIweHo17zdv8ORbD+GujGqn9UiQcQYQqGgFRmwnXF9j0351MtOZfJ2jQ8giMDyzjfys2xn3BAM88jrfjvNnxc6q2hhMe39XUe72QQmt2vsIiMO9ttrz6Z36QAeoxtHos4vtGfyex5qUbe/53Bar5i6OyqZBYw== rsa-key-packet-infra
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKN10bbtgVGiZsqGCnj6SYvmguD0JPs1/sAao2GTodb5rSjqs3BC5AJ2SIEpEz1WHxoGPItxRmnPNqVx6physdFmZmf53fiy0jpW+JL/P12Xl4NcXb13G3bOH1tuineMYVl7P3JWG5CJoUaDtUyEZacGQDV3Sk7kgyHT9E1nwqC114T+Pi/Xn2ze7bx0Pt3DQdvxcLmcCx43VhGbocFr8nkP//6cLLcafPwOp3zkPtTn/AfxzMChj54pyoXkgAgM9X+NKazETvNH1KD1bRzENR+wvo9EQL206ISJ/iN+0WgDGX67YTtAGDBOQOU9JRYOsESQT1yOfLcFhlH/kigzzD studarus@ubuntu-512mb-sfo1-01
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCuP0CZE8AYnbm8gxecCxKeRw0wHRyryd+FKmNNsdr0d3UvfCbqNzLigrqEBZsKpofi3M4qCWNpKRyfhnjPynLTQjP1vnX9AbL9UGoiHxScfvh3skntTYMs9ezJRd0rMJJZO76FPo8bJLDlwxAQl8m/nuj3HfYiO5hYE7P+a3rhsJh4nEfBb7xh+Q5yM0PWObkkBl6IRiBYjlcsXNZHgTA5kNuihUk5bHqAw54sHh05DhpgOITpTw4LFbh4Ew2NKq49dEb2xbTuAyAr2DHNOGgIwKEZpwtKZEIGEuiLbb4DQRsfivrvyOjnK2NFjQzGyNOHfsOldWHRQwUKUs8nrxKdXvqcrfMnSVaibeYK2TRL+6jd9kc5SIhWI3XLm7HbX7uXMD7/JQrkL25Rcs6nndDCH72DJLz+ynA/T5umMbNBQ9tybL5z73IOpfShRGjQYego22CxDOy7e/5OEMHNoksbFb1S02viM9O2puS7LDqqfT9JIbbPqCrbRi/zOXo0f4EXo6xKUAmd8qlV+6f/p57/qFihzQDaRFVlFEH3k7qwsw7PYGUTwkPaThe6xyZN6D5jqxCZU3aSYu+FGb0oYo+M5IxOm0Cb4NNsvvkRPxWtwSayfFGu6+m/+/RyA3GBcAMev7AuyKN+K2vGMsLagHOx4i+5ZAcUwGzLeXAENNum3w== pabelanger@github
5 changes: 5 additions & 0 deletions terraform/deployment_host.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# OSA deployment host packages
apt-get install -y aptitude build-essential git ntp ntpdate python-dev sudo
git clone -b 18.1.1 https://git.openstack.org/openstack/openstack-ansible /opt/openstack-ansible
(cd /opt/openstack-ansible; scripts/bootstrap-ansible.sh)
cp -R /opt/openstack-ansible/etc/openstack_deploy/ /etc/openstack_deploy
4 changes: 4 additions & 0 deletions terraform/id_rsa.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6d3lJdnWzH8l4Pf55TeTfAy/3GUaI0BYdwZljpNaX/L5hVvOWVPaUIBuxuTylf5MBxAuotv8ZxGFkUaWTXJaLzRUZ8l5d8jztdft58v4rHcTthdTafKC50JPw+WBhHgWLRxddvcxW/ou6R5X9VLKZ/wCwTCwQgZEecf5s3xXQjvFN2urI8nrauVMLypDfl0hwaPylf0FBfTApdscAFQY+RAvPU1Sb1Mp2UVzB3+bblGHNa5IE/OJDujnisEDAM1hbkyyRWQWzh7yXqML9G5LNF0E5KYAioAgUjmPKnik4B/aXQhDEip0mVpuhM8iPvOVGW+z65Q89hq1sIbLJnVRd studarus@shell
ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAoc+BHLERUqmw9dvR0H+36lAEs4SHzO0Eadx2xiqavhrYyJGWe0AxmLs2upRjEUtuOP22uaTW0QE7Fb31KygiN96jgac219zTsedKvcq/vAnNvHYCi2I07+yg9T5Lk/FOPzRzGLR+sSnqFnw+Hgz75JDmtSOxCJODhFTMFG9cHRfjq3Cu1cImed1SkLIweHo17zdv8ORbD+GujGqn9UiQcQYQqGgFRmwnXF9j0351MtOZfJ2jQ8giMDyzjfys2xn3BAM88jrfjvNnxc6q2hhMe39XUe72QQmt2vsIiMO9ttrz6Z36QAeoxtHos4vtGfyex5qUbe/53Bar5i6OyqZBYw== rsa-key-packet-infra
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKN10bbtgVGiZsqGCnj6SYvmguD0JPs1/sAao2GTodb5rSjqs3BC5AJ2SIEpEz1WHxoGPItxRmnPNqVx6physdFmZmf53fiy0jpW+JL/P12Xl4NcXb13G3bOH1tuineMYVl7P3JWG5CJoUaDtUyEZacGQDV3Sk7kgyHT9E1nwqC114T+Pi/Xn2ze7bx0Pt3DQdvxcLmcCx43VhGbocFr8nkP//6cLLcafPwOp3zkPtTn/AfxzMChj54pyoXkgAgM9X+NKazETvNH1KD1bRzENR+wvo9EQL206ISJ/iN+0WgDGX67YTtAGDBOQOU9JRYOsESQT1yOfLcFhlH/kigzzD studarus@ubuntu-512mb-sfo1-01
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCuP0CZE8AYnbm8gxecCxKeRw0wHRyryd+FKmNNsdr0d3UvfCbqNzLigrqEBZsKpofi3M4qCWNpKRyfhnjPynLTQjP1vnX9AbL9UGoiHxScfvh3skntTYMs9ezJRd0rMJJZO76FPo8bJLDlwxAQl8m/nuj3HfYiO5hYE7P+a3rhsJh4nEfBb7xh+Q5yM0PWObkkBl6IRiBYjlcsXNZHgTA5kNuihUk5bHqAw54sHh05DhpgOITpTw4LFbh4Ew2NKq49dEb2xbTuAyAr2DHNOGgIwKEZpwtKZEIGEuiLbb4DQRsfivrvyOjnK2NFjQzGyNOHfsOldWHRQwUKUs8nrxKdXvqcrfMnSVaibeYK2TRL+6jd9kc5SIhWI3XLm7HbX7uXMD7/JQrkL25Rcs6nndDCH72DJLz+ynA/T5umMbNBQ9tybL5z73IOpfShRGjQYego22CxDOy7e/5OEMHNoksbFb1S02viM9O2puS7LDqqfT9JIbbPqCrbRi/zOXo0f4EXo6xKUAmd8qlV+6f/p57/qFihzQDaRFVlFEH3k7qwsw7PYGUTwkPaThe6xyZN6D5jqxCZU3aSYu+FGb0oYo+M5IxOm0Cb4NNsvvkRPxWtwSayfFGu6+m/+/RyA3GBcAMev7AuyKN+K2vGMsLagHOx4i+5ZAcUwGzLeXAENNum3w== pabelanger@github
66 changes: 66 additions & 0 deletions terraform/openstack_user_config-yml.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
cidr_networks: &cidr_networks
container: ${container_nw}

used_ips:
- ${all_host_private_ips}
- ${all_host_public_ips}

global_overrides:
cidr_networks: *cidr_networks
#
# The below domain name must resolve to an IP address
# in the CIDR specified in haproxy_keepalived_external_vip_cidr.
# If using different protocols (https/http) for the public/internal
# endpoints the two addresses must be different.
#
tunnel_bridge: "br-mgmt"
management_bridge: "br-mgmt"
provider_networks:
- network:
container_bridge: "br-mgmt"
container_type: "veth"
container_interface: "eth1"
ip_from_q: "container"
type: "vxlan"
range: "1:1000"
net_name: "vxlan"
group_binds:
- all_containers
- hosts
is_container_address: true
is_ssh_address: true
static_routes:
# Route to container networks
- cidr: ${container_nw}
gateway: ${private_gw}
- network:
container_bridge: "br-flat"
container_type: "veth"
container_interface: "eth12"
container_mtu: 8900
host_bind_override: vup-flat
type: "flat"
net_name: "flat"
group_binds:
- neutron_linuxbridge_agent

###
### Infrastructure
###

_infrastructure_hosts: &infrastructure_hosts
${infrastructure_hosts}

shared-infra_hosts: *infrastructure_hosts
repo-infra_hosts: *infrastructure_hosts
haproxy_hosts: *infrastructure_hosts
identity_hosts: *infrastructure_hosts
image_hosts: *infrastructure_hosts
compute-infra_hosts: *infrastructure_hosts
dashboard_hosts: *infrastructure_hosts
network_hosts: *infrastructure_hosts

# nova hypervisors
compute_hosts: &compute_hosts
${compute_hosts}
80 changes: 80 additions & 0 deletions terraform/openstack_user_config.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
data "template_file" "infrastructure_hosts" {
depends_on = [
"packet_device.control",
]

count = "${var.control_count}"

template = <<JSON
$${hostname}:
ip: $${public_ip}
JSON

vars {
public_ip = "${element(packet_device.control.*.access_public_ipv4, count.index)}"
hostname = "${element(packet_device.control.*.hostname, count.index)}"
}
}

data "template_file" "compute_hosts" {
depends_on = [
"packet_device.compute",
]

count = "${var.compute_count}"

template = <<JSON
$${hostname}:
ip: $${public_ip}
JSON

vars {
public_ip = "${element(packet_device.compute.*.access_public_ipv4, count.index)}"
hostname = "${element(packet_device.compute.*.hostname, count.index)}"
}
}

data "template_file" "openstack_user_config" {
template = "${file("${path.module}/openstack_user_config-yml.tpl")}"

vars {
infrastructure_hosts = "${join(",", data.template_file.infrastructure_hosts.*.rendered)}"
compute_hosts = "${join(",", data.template_file.compute_hosts.*.rendered)}"

control_hostnames = "${jsonencode(join(",", packet_device.control.*.hostname))}"
control_public_ips = "${join(",",packet_device.control.*.access_public_ipv4)}"
compute_public_ips = "${join(",",packet_device.compute.*.access_public_ipv4)}"

control_private_ip = "${packet_device.control.0.access_private_ipv4}"
private_cidr = "${lookup(packet_device.control.0.network[2], "cidr")}"
private_gw = "${lookup(packet_device.control.0.network[2], "gateway")}"

# subnet assigned to the controller for containers
container_nw = "${packet_ip_attachment.container_ip_block.cidr_notation}"

all_host_private_ips = "${join(",",packet_device.control.*.access_private_ipv4,
packet_device.compute.*.access_private_ipv4)}"

all_host_public_ips = "${join(",",packet_device.control.*.access_public_ipv4,
packet_device.compute.*.access_public_ipv4)}"
}
}

resource "null_resource" "inventory" {
triggers {
template_rendered = "${data.template_file.openstack_user_config.rendered}"
}
provisioner "local-exec" {
command = "echo '${data.template_file.openstack_user_config.rendered}' > ${var.openstack_user_config_file}"
}
provisioner "file" {
connection {
type = "ssh"
user = "root"
host = "${packet_device.control.*.access_public_ipv4}"
private_key = "${file("${var.cloud_ssh_key_path}")}"
}
source = "${var.openstack_user_config_file}"
destination = "/etc/openstack_deploy/openstack_user_config.yml"
}
}
Loading