Skip to content
Closed
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.idea/workspace.xml
.DS_Store
*.tfstate
.terraform/
terraform.tfvars
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,40 @@ To remove the VM's that have been deployed run `terraform destroy --force`

**Please be aware that you will be responsible for the usage charges with Digital Ocean**

## vSphere quick start

The vsphere folder contains terraform code to stand up a single Rancher server instance with a 3 node cluster attached to it.

This terraform setup will:

- Create a VM in vSphere running `rancher/rancher` version specified in `rancher_version`
- Create a custom cluster called `qs-cluster`
- Start `count_agent_all_nodes` amount of VMs in vSphere and add them to the custom cluster with all roles

### How to use

#### Create RancherOS template

The terraform setup creates VMs by cloning a RancherOS template that must be made available in vCenter:

1. Download the RancherOS OVA appliance from https://transfer.sh/FZfU3/rancheros-v1.4.0-vapp.ova
2. Import the OVA file by right-clicking on a cluster or host in the inventory and selecting "Deploy OVF template...".
3. Mark the resulting VM as template -> "Convert to template".
4. Note the name/path of the template.

#### Run the terraform code

1. Clone this repository and go into the `vsphere` subfolder
2. Move the file `terraform.tfvars.example` to `terraform.tfvars` and edit (see inline explanation)
3. Run `terraform init`
4. Run `terraform apply`

When provisioning has finished you will be given the url to connect to the Rancher Server.

### How to Remove

To remove the VM's that have been deployed run `terraform destroy --force`

## Vagrant quick start

The vagrant folder contains a vagrant code to stand up a single Rancher server instance with a 3 node cluster attached to it.
Expand Down
23 changes: 23 additions & 0 deletions vsphere/cloud_config.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Renders the cloud-config file for the server
data "template_file" "server" {
template = "${file("${path.module}/files/cloud-config-server.tpl")}"

vars {
authorized_key = "${tls_private_key.provisioning_key.public_key_openssh}"
hostname = "${local.server_name_prefix}"
docker_version = "${var.node_docker_version}"
rancher_version= "${var.rancher_version}"
}
}

# Renders the cloud-config file for the cluster nodes
data "template_file" "cluster" {
template = "${file("${path.module}/files/cloud-config-cluster.tpl")}"
count = "${var.rancher_num_cluster_nodes}"

vars {
authorized_key = "${tls_private_key.provisioning_key.public_key_openssh}"
hostname = "${local.cluster_nodes_name_prefix}-${count.index + 1}"
docker_version = "${var.node_docker_version}"
}
}
32 changes: 32 additions & 0 deletions vsphere/data_sources.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
data "vsphere_datacenter" "dc" {
name = "${var.vsphere_datacenter}"
}

# Use count with tenary operator for conditional fetching of this data source
data "vsphere_compute_cluster" "cluster" {
count = "${var.vsphere_cluster != "" ? 1 : 0}"
name = "${var.vsphere_cluster}"
datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

# Use count with tenary operator for conditional fetching of this data source
data "vsphere_host" "host" {
count = "${var.vsphere_host != "" ? 1 : 0}"
name = "${var.vsphere_host}"
datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_datastore" "datastore" {
name = "${var.vsphere_datastore}"
datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_network" "network" {
name = "${var.vsphere_network}"
datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_virtual_machine" "template" {
name = "${var.vsphere_template}"
datacenter_id = "${data.vsphere_datacenter.dc.id}"
}
104 changes: 104 additions & 0 deletions vsphere/files/agent_bootstrap.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/bin/sh
set -x

curlimage=appropriate/curl
jqimage=stedolan/jq
cluster_name=qs-cluster

if [ $# -lt 2 ]; then
echo "required argument missing"
exit 1
fi

rancher_server_ip=$1
rancher_password=$2

for image in $curlimage $jqimage; do
until docker inspect $image > /dev/null 2>&1; do
docker pull $image
sleep 2
done
done

while true; do
docker run --rm $curlimage -sLk https://$rancher_server_ip/ping && break
sleep 5
done

# Login
while true; do

LOGINRESPONSE=$(docker run \
--rm \
$curlimage \
-s "https://$rancher_server_ip/v3-public/localProviders/local?action=login" -H 'content-type: application/json' --data-binary '{"username":"admin","password":"'$rancher_password'"}' --insecure)
LOGINTOKEN=$(echo $LOGINRESPONSE | docker run --rm -i $jqimage -r .token)

if [ "$LOGINTOKEN" != "null" ]; then
break
else
sleep 5
fi
done

# Get the Agent Image from the rancher server
while true; do
AGENTIMAGE=$(docker run \
--rm \
$curlimage \
-sLk \
-H "Authorization: Bearer $LOGINTOKEN" \
"https://$rancher_server_ip/v3/settings/agent-image" | docker run --rm -i $jqimage -r '.value')

if [ -n "$AGENTIMAGE" ]; then
break
else
sleep 5
fi
done

until docker inspect $AGENTIMAGE > /dev/null 2>&1; do
docker pull $AGENTIMAGE
sleep 2
done

# Test if cluster is created
while true; do
CLUSTERID=$(docker run \
--rm \
$curlimage \
-sLk \
-H "Authorization: Bearer $LOGINTOKEN" \
"https://$rancher_server_ip/v3/clusters?name=$cluster_name" | docker run --rm -i $jqimage -r '.data[].id')

if [ -n "$CLUSTERID" ]; then
break
else
sleep 5
fi
done

ROLEFLAG="all-roles"

# Get token
# Test if cluster is created
while true; do
AGENTCMD=$(docker run \
--rm \
$curlimage \
-sLk \
-H "Authorization: Bearer $LOGINTOKEN" \
"https://$rancher_server_ip/v3/clusterregistrationtoken?clusterId=$CLUSTERID" | docker run --rm -i $jqimage -r '.data[].nodeCommand' | head -1)

if [ -n "$AGENTCMD" ]; then
break
else
sleep 5
fi
done

# Combine command and flags
COMPLETECMD="$AGENTCMD --$ROLEFLAG"

# Run command
$COMPLETECMD
7 changes: 7 additions & 0 deletions vsphere/files/cloud-config-cluster.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#cloud-config
hostname: ${hostname}
ssh_authorized_keys:
- ${authorized_key}
rancher:
docker:
engine: docker-${docker_version}
17 changes: 17 additions & 0 deletions vsphere/files/cloud-config-server.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#cloud-config
hostname: ${hostname}
ssh_authorized_keys:
- ${authorized_key}
rancher:
docker:
engine: docker-${docker_version}
services:
rancher-qs-server:
image: rancher/rancher:${rancher_version}
restart: unless-stopped
privileged: false
ports:
- 80:80
- 443:443
volumes:
- /root/rancher:/var/lib/rancher
64 changes: 64 additions & 0 deletions vsphere/files/server_bootstrap.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/sh
set -x

curlimage=appropriate/curl
jqimage=stedolan/jq
cluster_name=qs-cluster

if [ $# -lt 1 ]; then
echo "required argument missing"
exit 1
fi

password=$1

for image in $curlimage $jqimage; do
docker pull $image
sleep 2
done

while true; do
docker run --rm --net=host $curlimage -sLk https://127.0.0.1/ping && break
sleep 5
done

# Login
while true; do

LOGINRESPONSE=$(docker run \
--rm \
--net=host \
$curlimage \
-s "https://127.0.0.1/v3-public/localProviders/local?action=login" -H 'content-type: application/json' --data-binary '{"username":"admin","password":"admin"}' --insecure)
LOGINTOKEN=$(echo $LOGINRESPONSE | docker run --rm -i $jqimage -r .token)
echo "Login Token is $LOGINTOKEN"
if [ "$LOGINTOKEN" != "null" ]; then
break
else
sleep 5
fi
done


# Change password
payload="{\"currentPassword\":\"admin\",\"newPassword\":\"$password\"}"
docker run --rm --net=host $curlimage -s "https://127.0.0.1/v3/users?action=changepassword" -H "content-type: application/json" -H "Authorization: Bearer $LOGINTOKEN" --data-binary $payload --insecure

# Create API key
APIRESPONSE=$(docker run --rm --net=host $curlimage -s 'https://127.0.0.1/v3/token' -H 'content-type: application/json' -H "Authorization: Bearer $LOGINTOKEN" --data-binary '{"type":"token","description":"automation"}' --insecure)

# Extract and store token
APITOKEN=`echo $APIRESPONSE | docker run --rm -i $jqimage -r .token`

# Configure server-url
RANCHER_SERVER="https://$(ifconfig eth0 | grep 'inet addr' | cut -d: -f2 | awk '{print $1}')"
docker run --rm --net=host $curlimage -s 'https://127.0.0.1/v3/settings/server-url' -H 'content-type: application/json' -H "Authorization: Bearer $APITOKEN" -X PUT --data-binary '{"name":"server-url","value":"'$RANCHER_SERVER'"}' --insecure

# Create cluster
CLUSTERRESPONSE=$(docker run --rm --net=host $curlimage -s 'https://127.0.0.1/v3/cluster' -H 'content-type: application/json' -H "Authorization: Bearer $APITOKEN" --data-binary '{"type":"cluster","rancherKubernetesEngineConfig":{"addonJobTimeout":30,"ignoreDockerVersion":true,"sshAgentAuth":false,"type":"rancherKubernetesEngineConfig","authentication":{"type":"authnConfig","strategy":"x509"},"network":{"type":"networkConfig","plugin":"canal"},"ingress":{"type":"ingressConfig","provider":"nginx"},"services":{"type":"rkeConfigServices","kubeApi":{"podSecurityPolicy":false,"type":"kubeAPIService"},"etcd":{"snapshot":false,"type":"etcdService","extraArgs":{"heartbeat-interval":500,"election-timeout":5000}}}},"name":"'$cluster_name'"}' --insecure)

# Extract clusterid to use for generating the docker run command
CLUSTERID=`echo $CLUSTERRESPONSE | docker run --rm -i $jqimage -r .id`

# Generate registrationtoken
docker run --rm --net=host $curlimage -s 'https://127.0.0.1/v3/clusterregistrationtoken' -H 'content-type: application/json' -H "Authorization: Bearer $APITOKEN" --data-binary '{"type":"clusterRegistrationToken","clusterId":"'$CLUSTERID'"}' --insecure
7 changes: 7 additions & 0 deletions vsphere/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
locals {
server_name_prefix = "rancher-qs-server"
cluster_nodes_name_prefix = "rancher-qs-node"
# Some trickery to work around limitation of terrafom tenary operator
# Allows the user to specify either the name of a cluster or an ESXi host
pool_id = "${var.vsphere_cluster != "" ? join("", data.vsphere_compute_cluster.cluster.*.resource_pool_id) : join("", data.vsphere_host.host.*.resource_pool_id)}"
}
3 changes: 3 additions & 0 deletions vsphere/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "rancher-url" {
value = ["https://${vsphere_virtual_machine.server.default_ip_address}"]
}
8 changes: 8 additions & 0 deletions vsphere/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Configure the vSphere Provider
provider "vsphere" {
version = "~> 1.8"
user = "${var.vcenter_user}"
password = "${var.vcenter_password}"
vsphere_server = "${var.vcenter_server}"
allow_unverified_ssl = "${var.vcenter_insecure}"
}
5 changes: 5 additions & 0 deletions vsphere/provisioner.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Generate a short-lived SSH key for the provisioner to access the nodes.
# The key is removed from the nodes during provisioning.
resource "tls_private_key" "provisioning_key" {
algorithm = "RSA"
}
23 changes: 23 additions & 0 deletions vsphere/terraform.tfvars.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
vcenter_user = "username"
vcenter_password = "password"
vcenter_server = "vcenter.acme.com"
vcenter_insecure = false

rancher_admin_password = "changeme"
rancher_version = "v2.0.8"
rancher_num_cluster_nodes = 3

node_num_cpus = 2
node_memory_gb = 4
node_docker_version = "17.03.1-ce"

vsphere_datacenter = "HE-FMT"
vsphere_host = "192.168.100.222"
vsphere_datastore = "datastore-192-168-100-222"
vsphere_network = "VM Network"
vsphere_template = "vm-templates/rancheros-v1.4.0-golden"
vsphere_folder = "rancher-qs"

authorized_ssh_key = "ssh-rsa abcdef user@host",


Loading