August 26, 2016 | Kubernetes
This post is the second of a series of three tutorial articles introducing a sample, tutorial project, demonstrating how to provision Kubernetes on AWS from scratch, using Terraform and Ansible. To understand the goal of the project, you’d better start from the first part.
WRITTEN BY
Part 1: Provision the infrastructure, with Terraform.
Part 2 (this article): Install and configure Kubernetes, with Ansible.
Part 3: Complete setup and smoke test it, deploying a nginx service.
The complete working project is available here: https://github.com/opencredo/k8s-terraform-ansible-sample
In the previous article, we created all AWS resources, using Terraform. No Kubernetes component has been installed yet.
We have 9 EC instances (hosts, in Ansible terms), 3 of each type (group, for Ansible):
All hosts need the certificates we generated, for HTTPS.
First of all, we have to install Python 2.5+ on all machines.
The Ansible part of the project is organised as suggested by Ansible documentation. We also have multiple playbooks, to run independently:
infra.yaml
)kubectl.yaml
)kubernetes-routing.yaml
)kubernetes-nginx.yaml
) + manual operationsThis article walks through the first playbook (infra.yaml
).
The code snippets have been simplified. Please refer to project repository for the complete version.
The first playbook takes care of bootstrapping Ansible and installing Kubernetes components. Actual tasks are separate in roles: common
(executed on all hosts); one role per machine type: controller
, etcd
and worker
.
Before proceeding, we have to understand how Ansible identifies and find hosts.
Ansible works on groups of hosts. Each host must have a unique handle and address to SSH into the box.
The most basic approach is using a static inventory, a hardwired file associating groups to hosts and specifying the IP address (or DNS name) of each host.
A more realistic approach uses a Dynamic Inventory, and a static file to define groups, based on instance tags. For AWS, Ansible provides an EC2 AWS Dynamic Inventory script out-of-the-box.
The configuration file ec2.ini
, downloaded from Ansible repo, requires some change. It is very long, so here are the modified parameters only:
Note we use instance tags to filter and identify hosts and we use IP addresses for connecting to the machines.
A separate file defines groups, based on instance tags. It creates nicely named groups, controller
, etcd
and worker
(we might have used groups weirdly called tag_ansibleNodeType_worker
…). If we add new hosts to a group, this file remains untouched.
To make the inventory work, we put Dynamic Inventory Python script and configuration file in the same directory with groups file.
ansible/ hosts/ ec2.py ec2.ini groups
The final step is configuring Ansible to use this directory as inventory. In ansible.cfg
:
Now we are ready to execute the playbook (infra.yaml
) to install all components. The first step is installing Python on all boxes with a raw
module. It executes a shell command remotely, via SSH, with no bell and whistle.
The second part of the playbook install and configure all Kubernetes components. It plays different roles on hosts, depending on groups. Note that groups and roles have identical names, but this is not a general rule.
Ansible executes the common role (omitted here) on all machines. All other roles do the real job. They install, set up and start services using systemd:
Here are the tasks of etcd
role . Other roles are not substantially different.
We generate etcd.service
from a template. Ports are hardwired (may be externalised as variables), but hosts IP addresses are facts gathered by Ansible.
The most significant simplifications, compared to a real world project, concern two aspects:
The infra.yaml
playbook has installed and run all the services required by Kubernetes. In the next article, we will set up routing between Containers, to allow Kubernetes Pods living on different nodes talking each other.
This blog is written exclusively by the OpenCredo team. We do not accept external contributions.