karch
is a Terraform module based on
kops aiming at managing (multiple)
Kubernetes clusters on AWS. You can see it as "Terraform bindings for kops".
It essentially aims at making it easier to share Kubernetes cluster topologies or even entire stacks built atop Kubernetes.
kops
has become the standard, non-opinionated way of deploying Kubernetes
clusters on AWS and can even generate Terraform code. However, this approach has
some limits:
- Values of resources managed by
kops
, such as the id of the cluster's VPC, subnets, etc... aren't really accessible from the rest of your codebase. - One needs one subfolder per cluster (which can be used as a Terraform module): creating a "cluster template" (masters + several IGs) that can easily be replicated across AWS regions & shared across teams isn't possible
It seemed that wrapping by wrapping the kops
CLI itself into a Terraform
module which really feels like a simple Terraform module could fulfil this
need for portable, repeatable infrastructure a bit better. Of course, keeping
the flexibility offered by kops
's cluster & instance group spec available by
exposing all the parameters it provides as Terraform variables felt essential.
Therefore, karch
aims at making it easy to encode Kubernetes cluster topologies
using Terraform infrastructure code. For instance, such a topology could be:
- an instance group for a pool of NginX ingress controllers, mounting ports
- one for your backend APIs
- one for stateful apps (databases, data stores...)
- one, with GPU instances, to run your ML pipeline
- with Kubernetes to orchestrate all types of workloads
- A Terraform library, written in plain HCL and using essentially
kops
,sh
andawk
. - A set of two Terraform modules
cluster
andig
. The former spawns a base cluster, in a new VPC, the latter can be used to spawn instance groups. - A wrapper around
kops
, instead of usingkops
directly, you'll be using a terraform module to create/update/delete yourkops
clusters. When necessary, this module will take care of rolling out your instance groups.
- A Terraform provider plugin. Writing such a plugin would be nice, but would require much more time to implement.
- For now,
karch
spawns only clusters with aprivate
topology. Adding the ability to createpublic
clusters will come next - For now,
karch
takes care of creating a VPC and Route53 zone for your cluster's subdomain. Being able to give it an already existing VPC and/or zone is on the roadmap
You'll only need kops
, kubectl
, sh
, and the aws-cli
(or at
least, an AWS account configured accordingly
under ~/.aws/credentials
).
To create a Kubernetes cluster, you can use the kops-cluster
module:
You can refer to ./kops-cluster/variables.tf
for a documented list of all the
variables you can pass to the module.
module "kops-cluster" {
source = "github.com/elafarge/karch/aws/cluster"
version = "1.7.1"
aws-region = "eu-west-1"
# Networking & connectivity
vpc-name = "kube-hq"
vpc-cidr = "10.70.0.0/16"
availability-zones = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
kops-topology = "private"
trusted-cidrs = "0.0.0.0/0"
admin-ssh-public-key-path = "~/.ssh/id_rsa.pub"
# DNS
main-zone-id = "example.com"
cluster-name = "kube-hq.example.com"
# Kops & Kuberntetes
kops-state-bucket = "example-com-kops-state"
# Master
master-availability-zones = ["eu-west-1a"]
master-image = "ami-109d6069"
# Bastion
bastion-image = "ami-109d6069"
# First minion instance group
minion-image = "ami-109d6069"
}
Here as well, it boils down to simply using a Terraform module. The list of
accepted variables can be found under ./kops-ig/variables.tf
.
module "ingress-ig" {
source = "github.com/elafarge/karch/aws/ig"
version = "1.7.1"
aws-region = "eu-west-1"
# Master cluster dependency hook
master-up = "${module.kops-cluster.master-up}"
# Global config
name = "ingress"
cluster-name = "kube-hq.example.com"
kops-state-bucket = "example-com-kops-state"
visibility = "private"
subnets = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
image = "ami-109d6069"
type = "t2.small"
volume-size = "16"
volume-type = "gp2"
min-size = 2
max-size = 3
node-labels = "${map("role.node", "ingress")}"
}
You can entirely rely on Terraform to update your cluster on terraform apply
.
Please note that we never run kops rolling-update
for cluster updates. You'll
need to run it manually. However, rolling updates can be automatically applied
for instance groups, with a configurable node rollout time interval.
Please note that from release tag tf13-v1.14.1, the repository now supports Terraform 13 syntax and thus is incompatible with Terraform 11 or before. We will continue to release from v1.15.x with Terraform 13 syntax going forward.
- Étienne Lafarge <etienne.lafarge at gmail.com>