Déployer Cilium et AKS avec Terraform (Partie 1)
Introduction
Cet été, j’ai pas mal parlé de Cilium et d’EKS. Mais je n’ai pas parlé de son déploiement avec Terraform. L’actualité de Terraform était un peu mouvementé cette été. Je ne voulais pas en rajouter. Pour changer, je vais regarder du côté de Microsoft et de son cloud Azure.
Je connais nettement mieux AWS à Azure. Mais j’ai vu qu’il était facile de déployer Cilium sur AKS. Notamment avec cette annonce. Alors je voulais me faire une petite idée si c’était le cas.
J’ai créé un repo git pour cela :
Si vous voulez que le code soit identique à celui qui est présenté ici, il faut utiliser la branche blog.
De quoi parle t’on ?
AKS est le service permettant d’utiliser des clusters kubernetes gérés par Azure. Cilium est un plugin réseau (CNI) créé par Isovalent. Un CNI est indispensable à la communication d’un cluster kubernetes. Pour plus d’information, n’hésitez pas à lire la première partie de EKS et Cilium. Il y a différentes possibilités pour installer Cilium sur AKS:
- Version azure: c’est Azure qui gère Cilium
- Version custom: c’est vous qui gèrez Cilium
Terraform est un outil de déploiement, créé par Hashicorp, sur les clouds. On va ainsi pouvoir déployer de façon automatisée un cluster kubernetes (AKS) avec cilium.
Je ne parlerai pas de la gestion du tfstate ou de la cicd. L’idée c’est : j’ai envie de voir ce que donne Cilium dans AKS. Je lance un terraform apply pour faire des tests.
Pré-requis
- Terraform (une version récente > 1.3)
- az cli (j’utilise la 2.50.0) : ligne de commande pour Azure (principalement pour s’identifier)
- jq : pour interpréter du json
- un compte Azure
Inputs obligatoires
Traditionnellement, le fichier variables.tf contient la liste des inputs nécessaires pour déployer. Il y a des inputs obligatoires, que je ne peux pas deviner pour vous, et des inputs facultatifs, qui sont customisables (par exemple quel type de déploiements de Cilium veux-tu faire ?).
Dans le fichier variables.tf, il y a deux variables obligatoires à indiquer avant de déployer, ce sont des identifiants pour Azure :
variable "resource_group_name" {
description = "Resource Group Name (az group list | jq -r '.[0].name')"
type = string
}
variable "location" {
description = "Location (az group list | jq -r '.[0].location')"
type = string
}
- resource_group_name : le nom de la resource Azure. Je suppose qu’on l’a déjà créé dans la console azure. Il y a bien un data source : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group . Mais il faut indiquer son nom, ça ne change pas grand chose. Donc je suis obligé de le mettre en dur (par exemple dans un fichier terraform.tfvars). S’il n’y en a qu’un comme chez moi, il suffit de taper dans un terminal :
az group list | jq -r '.[0].name'
- location : dans quel datacenter on déploie la solution. De la même manière pour le trouver si vous avez des restrictions, vous pouvez lancer cette commande :
az group list | jq -r '.[0].location'
Inputs facultatifs
Le reste des inputs sont “facultatifs”, ça permettra de customiser au mieux votre déploiement.
Dans le fichier variables.tf, il y a des données concernant le réseau : le vnet (le vpc d’aws version azure).
variable "vnet" {
description = "Feature of vnet"
type = object({ address_space = list(string), name = string })
default = {
address_space = ["10.0.0.0/8"]
name = "cilium-tf-helm"
}
}
variable "subnet_node" {
description = "Feature of subnet of node"
type = object({ address_prefixes = list(string), name = string })
default = {
address_prefixes = ["10.240.0.0/16"]
name = "nodesubnet"
}
}
variable "subnet_pod" {
description = "Feature of subnet of pod"
type = object({ address_prefixes = list(string), name = string })
default = {
address_prefixes = ["10.241.0.0/16"]
name = "podsubnet"
}
}
- La variable vnet : c’est pour définir le cidr du vnet et son nom
- La variable subnet_node : c’est pour définir le cidr du sous-réseau dédié aux nœuds AKS et son nom.
- La variable subnet_pod : c’est pour définir le cidr du sous-réseau dédié aux pods AKS et son nom. Cette variable est uniquement utile dans le cas de cilium géré par Azure.
Maintenant on passe au kubernetes géré par Azure, AKS:
variable "aks" {
description = "Feature of aks"
type = object({
name = string
version = string
dns_prefix = string
default_node_pool = object({
name = optional(string, "default")
node_count = optional(number, 3)
vm_size = optional(string, "Standard_DS2_v2")
})
})
default = {
name = "cilium-cluster-tf-helm"
version = "1.27.3"
dns_prefix = "cilium"
default_node_pool = {
name = "default"
node_count = 3
vm_size = "Standard_DS2_v2"
}
}
}
On va définir différents paramètres :
- name: le nom du cluster
- version: la version de kubernetes. La dernière version (1.14) de cilium gère la version 1.27. Donc j’ai choisi celle-là.
- dns_prefix: c’est pour l’url du de l’api de kubernetes.
- default_node_pool : la création des nœuds avec ses caractéristiques
Maintenant on passe à Cilium :
variable "cilium" {
description = "Feature of cilium"
type = object({
type = string
version = optional(string, "1.14.3")
kube-proxy-replacement = optional(bool, false)
ebpf-hostrouting = optional(bool, false)
hubble = optional(bool, false)
hubble-ui = optional(bool, false)
})
default = {
type = "cilium_custom" #other options: cilium_azure|byocni
version = "1.14.3"
kube-proxy-replacement = true
ebpf-hostrouting = true
hubble = true
hubble-ui = true
}
}
type : on a trois options possibles :
- byocni : pas d’installation de cilium (ça permet de faire l’installation de cilium ou d’un autre cni après coup)
- cilium_azure : cilium géré par azure
- cilium_custom : cilium géré par soi-même (variante de byocni)
Une fois qu’on a décidé d’utiliser cilium géré par azure, il sera plus difficile de passer par un cilium géré par soi-même ou inversement sans devoir tout redéployer.
Les autres arguments sont uniquement disponibles pour cilium_custom:
- version : la version de cilium (j’ai pris la dernière en date : la 1.14)
- kube-proxy-replacement : remplace-t-on kube-proxy par cilium ?
- ebpf-hostrouting : utilise-t-on ebpf pour le host routing (désolé pour l’anglicisme) ? On doit également avoir remplacé kube-proxy par cilium pour que cette option soit possible.
- hubble : installe-t-on hubble ?
- hubble-ui : installe-t-on hubble ui ?
Une fois qu’on a décidé de remplacer kube-proxy, il sera plus compliqué de revenir en arrière.
Si vous ne savez pas ce que sont ces différentes options, voici quelques images qui vous aideront à comprendre leurs intérêts :
Voilà tout ce qui est faisable dans ce repo git (dans la branche blog).
Le déploiement
Pour déployer, il ne faut pas oublier de s’authentifier auprès d’Azure :
az login -u "$login" -p "$password"
cat terraform.azure.tfvars # ne pas oublier les variables obligatoires
resource_group_name = "xxxxxxxxxx"
location = "southcentralus" # par exemple
Les dépendances sont relativement simples :
- terraform : version récente, c’est à dire > 1.3
- kubectl : en cas de kube-proxy replacement, Azure ne permet pas encore de ne pas installer kube-proxy avec l’API d’Azure.
Les providers (plugin terraform) utilisés sont assez classiques :
- azurerm: pour le déploiement sur Azure
- helm: pour l’installation de cilium
- local: pour la création du fichier kubeconfig
Pour le déploiement c’est classique :
terraform init
terraform plan
terraform apply -var-file terraform.azure.tfvars
Cela va créer un cluster AKS et un fichier kubeconfig.
Si on veut s’amuser avec kubectl, il suffit d’exporter la variable KUBECONFIG :
export KUBECONFIG=./kubeconfig
La première partie est finie. Si vous connaissez bien terraform, vous pouvez déjà jouer avec les différentes options. Dans la prochaine partie, nous verrons les ressources et modules utilisés pour déployer et nous ferons le tour de la boutique de Cilium géré par Azure.
Contactez-moi sur Linkedin.