Aller au contenu principal

Infrastructure as Code avec Hikube (legacy)

Méthode retirée

Cette méthode pilotait Hikube au travers d'un kubeconfig de projet et de manifestes Kubernetes. Le kubeconfig de projet n'est plus disponible : cette méthode ne fonctionne plus. Cette page est conservée pour référence.

Automatisation : l'API publique

Pour automatiser la gestion de vos ressources, utilisez l'API publique Hikube, avec des clés d'API rattachées à un projet ; elle est aujourd'hui en préversion. Un provider Terraform dédié, fondé sur cette API, est envisagé. Pour gérer vos ressources à la main, utilisez la console Hikube.

Vous pouvez utiliser Terraform pour gérer votre infrastructure Hikube de manière déclarative et reproductible, au travers des providers Kubernetes.


Configuration​

Prérequis​

  • Un kubeconfig de projet. Il n'est plus disponible : voir l'avertissement en tête de page.
  • Terraform (version >= 1.0)
  • kubectl

Provider Kubernetes​

main.tf
terraform {
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.24"
}
kubectl = {
source = "gavinbunney/kubectl"
version = "~> 1.14"
}
}
}

provider "kubernetes" {
config_path = "~/.kube/config"
}

provider "kubectl" {
config_path = "~/.kube/config"
}

Variables​

variables.tf
variable "ssh_public_key" {
description = "Clé SSH publique pour l'accès aux VMs"
type = string
}

variable "cluster_name" {
description = "Nom du cluster Kubernetes"
type = string
default = "terraform-cluster"
}

variable "vm_name" {
description = "Nom de la machine virtuelle"
type = string
default = "terraform-vm"
}

Exemples​

Déployer un Cluster Kubernetes​

kubernetes.tf
resource "kubectl_manifest" "kubernetes_cluster" {
yaml_body = yamlencode({
apiVersion = "apps.cozystack.io/v1alpha1"
kind = "Kubernetes"
metadata = {
name = var.cluster_name
}
spec = {
version = "v1.34"
storageClass = "replicated"

controlPlane = {
replicas = 2
}

nodeGroups = {
general = {
minReplicas = 1
maxReplicas = 5
instanceType = "s1.large"
ephemeralStorage = "50Gi"
roles = ["ingress-nginx"]
}
# Exemple de groupe GPU (nécessite l'addon gpuOperator ci-dessous)
# gpu = {
# minReplicas = 0
# maxReplicas = 4
# instanceType = "u1.2xlarge"
# ephemeralStorage = "200Gi"
# gpus = [{ name = "nvidia.com/AD102GL_L40S" }]
# roles = []
# }
}

addons = {
certManager = {
enabled = true
}
ingressNginx = {
enabled = true
hosts = [
"${var.cluster_name}.example.com"
]
}
# Requis pour exposer les GPU aux pods d'un node group GPU
# gpuOperator = {
# enabled = true
# }
}
}
})
}

# Récupérer le kubeconfig
data "kubernetes_secret" "cluster_kubeconfig" {
depends_on = [kubectl_manifest.kubernetes_cluster]

metadata {
name = "kubernetes-${var.cluster_name}-admin-kubeconfig"
}
}

# Sauvegarder le kubeconfig
resource "local_file" "kubeconfig" {
content = base64decode(
data.kubernetes_secret.cluster_kubeconfig.data["super-admin.conf"]
)
filename = "${path.module}/${var.cluster_name}-kubeconfig.yaml"
file_permission = "0600"
}

Déployer une Machine Virtuelle​

virtual-machine.tf
# Le disque est une ressource VMDisk distincte, référencée par la VM
resource "kubectl_manifest" "vm_disk" {
yaml_body = yamlencode({
apiVersion = "apps.cozystack.io/v1alpha1"
kind = "VMDisk"
metadata = {
name = "${var.vm_name}-disk"
}
spec = {
source = {
image = {
name = "ubuntu-2404"
}
}
storage = "50Gi"
storageClass = "replicated"
}
})
}

resource "kubectl_manifest" "virtual_machine" {
depends_on = [kubectl_manifest.vm_disk]

yaml_body = yamlencode({
apiVersion = "apps.cozystack.io/v1alpha1"
kind = "VMInstance"
metadata = {
name = var.vm_name
}
spec = {
runStrategy = "Always"
instanceProfile = "ubuntu"
instanceType = "u1.xlarge"

disks = [
{
name = "${var.vm_name}-disk"
}
]

external = true
externalMethod = "PortList"
externalPorts = [22, 80, 443]

sshKeys = [var.ssh_public_key]

cloudInit = <<-EOT
#cloud-config
users:
- name: ubuntu
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
ssh_authorized_keys:
- ${var.ssh_public_key}

package_update: true
packages:
- curl
- wget
- git
- docker.io

runcmd:
- systemctl enable docker
- systemctl start docker
- usermod -aG docker ubuntu
EOT
}
})
}

Déployer une VM avec GPU​

vm-gpu.tf
resource "kubectl_manifest" "vm_gpu_disk" {
yaml_body = yamlencode({
apiVersion = "apps.cozystack.io/v1alpha1"
kind = "VMDisk"
metadata = {
name = "gpu-vm-disk"
}
spec = {
source = {
image = {
name = "ubuntu-2404"
}
}
storage = "100Gi"
storageClass = "replicated"
}
})
}

resource "kubectl_manifest" "vm_gpu" {
depends_on = [kubectl_manifest.vm_gpu_disk]

yaml_body = yamlencode({
apiVersion = "apps.cozystack.io/v1alpha1"
kind = "VMInstance"
metadata = {
name = "gpu-vm"
}
spec = {
runStrategy = "Always"
instanceProfile = "ubuntu"
instanceType = "u1.xlarge"

gpus = [
{
# Modèles : nvidia.com/AD102GL_L40S, nvidia.com/GA100_A100_PCIE_80GB,
# nvidia.com/GA100_A100_SXM4_80GB, nvidia.com/GB202GL_RTX_PRO_6000_BLACKWELL_SERVER_EDITION
name = "nvidia.com/AD102GL_L40S"
}
]

disks = [
{
name = "gpu-vm-disk"
}
]

external = true
externalMethod = "PortList"
externalPorts = [22, 8888]

sshKeys = [var.ssh_public_key]

cloudInit = <<-EOT
#cloud-config
users:
- name: ubuntu
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash

package_update: true
packages:
- curl
- wget
- build-essential

runcmd:
# Installation pilotes NVIDIA
- wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.0-1_all.deb
- dpkg -i cuda-keyring_1.0-1_all.deb
- apt-get update
- apt-get install -y cuda-toolkit nvidia-driver-535
- nvidia-smi -pm 1
EOT
}
})
}

Déployer PostgreSQL​

postgresql.tf
resource "kubectl_manifest" "postgres" {
yaml_body = yamlencode({
apiVersion = "apps.cozystack.io/v1alpha1"
kind = "Postgres"
metadata = {
name = "terraform-postgres"
}
spec = {
external = false
size = "20Gi"
replicas = 2
storageClass = "replicated"

users = {
admin = {
password = var.postgres_password
}
}

databases = {
myapp = {
roles = {
admin = ["admin"]
}
}
}
}
})
}

variable "postgres_password" {
description = "Password for PostgreSQL admin user"
type = string
sensitive = true
}

Outputs et Variables​

Outputs utiles​

outputs.tf
output "cluster_kubeconfig" {
description = "Chemin vers le kubeconfig du cluster"
value = local_file.kubeconfig.filename
}

output "vm_status" {
description = "Commande pour vérifier le statut de la VM"
value = "kubectl get vminstance ${var.vm_name}"
}

output "postgres_connection" {
description = "Commande pour se connecter à PostgreSQL"
value = "kubectl exec -it postgres-terraform-postgres-0 -- psql -U admin -d myapp"
sensitive = true
}

Fichier terraform.tfvars​

terraform.tfvars
# Configuration de base
cluster_name = "my-prod-cluster"
vm_name = "my-app-vm"

# Votre clé SSH publique
ssh_public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQ... user@hostname"

# Mot de passe PostgreSQL
postgres_password = "your-secure-password-here"

Bonnes Pratiques​

Structure de projet​

hikube-terraform/
├── environments/
│ ├── dev/
│ ├── staging/
│ └── production/
├── modules/
│ ├── kubernetes/
│ ├── vm/
│ └── database/
└── shared/
├── variables.tf
└── outputs.tf

Commandes utiles​

# Initialiser Terraform
terraform init

# Planifier les changements
terraform plan

# Appliquer la configuration
terraform apply

# Vérifier les ressources créées
terraform show

# Nettoyer les ressources
terraform destroy

Références​