Cloud-init on GCE and terraform
Cloud-init is a great way to initialize machines on cloud providers and it’s pretty straightforwardly supported everywhere.
Here is my personal take on how I use it to manage my instances on GCE and particularly how I init chef nodes onto them using terraform
Using the following code :
module "my_cloud_init" {
source = "git@xxx:yyy/my-cloud-init-module.git"
chef_role = "my-role"
chef_environment = "my-env"
}
resource "google_compute_instance" "my_instance" {
name = "example-cloud-init"
machine_type = "n1-standard-1"
// omitted to keep things short
metadata = {
user-data = module.my_cloud_init.user_data
}
// omitted again
}
of course you will have noticed that once again, the magic happens using the instance metadata. here is the code of the module to generate the cloud-init instructions
variable "locale" {
description = "The locale to use"
default = "en_US.UTF-8"
}
variable "chef_role" {
description = "The chef role for this node"
default = "basic"
}
variable "chef_environment" {
description = "The chef environment for this node"
default = "dev-ew1"
}
data "template_file" "cloud_init" {
template = "${file("${path.module}/cloud-init.yaml.tpl")}"
vars = {
locale = var.locale
chef_role = var.chef_role
chef_environment = var.chef_environment
}
}
output "user_data" {
value = data.template_file.cloud_init.rendered
}
and the cloud-init.yaml.tpl
file :
#cloud-config
manage_etc_hosts: false
locale: ${locale}
timezone: UTC
runcmd:
- mkdir -p /etc/chef
# make sure this bucket has the correct and strict enough ACLs !!
# Also the instance service account must be able to read it of course
- gsutil cp -r "gs://my-bootstrap_bucket/path/*" /etc/chef
# first run must remove this file ! never keep it on your nodes
- chmod 0400 /etc/chef/org-validator.pem
# first run is on role basic. All nodes must execute it without any problem by default.
- chef-client -E ${chef_environment} -r "role[basic]"
- hostname=$(hostname -f)
# switch to the role for this very node
- knife node run_list -c /etc/chef/client.rb --config-option node_name=$${hostname} set $${hostname} "role[${chef_role}]"
- chef-client