Déployer Cilium et AKS avec Terraform (Partie 1)

Joseph Ligier
6 min readDec 1, 2023

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
}
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 :

eBPF Host Routing : on supprime pas mal de règles iptables
kube-proxy replacement : j’en ai déjà parlé ici
hubble : un peu comme tcpdump
hubble ui : un peu comme kiali (pour istio)

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 :

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.

--

--