Utilisation de Pulumi

Dans un nouveau dossier, nous créons les fichiers suivants :

  • Pulumi.yaml, qui définit les ressources Exoscale à créer (security group, règles de security group, cluster SKS, node pool et fichier kubeconfig)

  • Pulumi.demo.yaml, qui définit les options de configuration à appliquer à Pulumi.yaml afin de créer une stack spécifique nommée demo

name: sks-template 
runtime: yaml
description: SKS cluster management
config:
    zone:
        type: string
    version:
        type: string
    size:
        type: integer
    instanceType:
        type: string
    nodepoolSuffix:
        type: integer
        default: 0
outputs:
    kubeConfig: ${kubeconfig.kubeconfig}
resources:
    exoscale-provider:
        type: pulumi:providers:exoscale
        defaultProvider: true
        options:
            version: 0.59.2
    securityGroup:
        type: exoscale:SecurityGroup
        properties:
            description: Security group for Kubernetes nodes
            name: sg-${pulumi.stack}
    securityGroupRulesNodePorts:
        type: exoscale:SecurityGroupRule
        properties:
            securityGroupId: ${securityGroup.id}
            type: INGRESS
            protocol: TCP
            cidr: 0.0.0.0/0
            startPort: 30000
            endPort: 32767
    securityGroupRulesKubelet:
        type: exoscale:SecurityGroupRule
        properties:
            securityGroupId: ${securityGroup.id}
            type: INGRESS
            protocol: TCP
            userSecurityGroupId: ${securityGroup.id}
            startPort: 10250
            endPort: 10251
    securityGroupRulesPrometheus:
        type: exoscale:SecurityGroupRule
        properties:
            securityGroupId: ${securityGroup.id}
            type: INGRESS
            protocol: TCP
            userSecurityGroupId: ${securityGroup.id}
            startPort: 9100
            endPort: 9100
    securityGroupRulesCiliumVXLAN:
        type: exoscale:SecurityGroupRule
        properties:
            securityGroupId: ${securityGroup.id}
            type: INGRESS
            protocol: UDP
            userSecurityGroupId: ${securityGroup.id}
            startPort: 8472
            endPort: 8472
    securityGroupRulesCiliumHCICMP:
        type: exoscale:SecurityGroupRule
        properties:
            securityGroupId: ${securityGroup.id}
            type: INGRESS
            protocol: ICMP
            userSecurityGroupId: ${securityGroup.id}
            icmpCode: 0
            icmpType: 8
    securityGroupRulesCiliumHCTCP:
        type: exoscale:SecurityGroupRule
        properties:
            securityGroupId: ${securityGroup.id}
            type: INGRESS
            protocol: TCP
            userSecurityGroupId: ${securityGroup.id}
            startPort: 4240
            endPort: 4240
    cluster:
        type: exoscale:SksCluster
        properties:
            autoUpgrade: false
            cni: cilium
            description: demo SKS cluster
            exoscaleCcm: true
            exoscaleCsi: true
            metricsServer: true
            serviceLevel: starter
            name: sks-${pulumi.stack}
            zone: ${zone}
            version: ${version}
    nodepool:
        type: exoscale:SksNodepool
        properties:
            clusterId: ${cluster.id}
            name: sks-${pulumi.stack}-${nodepoolSuffix}
            zone: ${cluster.zone}
            instanceType: ${instanceType}
            size: ${size}
            securityGroupIds:
            - ${securityGroup.id}
        options:
            replaceOnChanges:
            - name
    kubeconfig:
        type: exoscale:SksKubeconfig
        properties:
            clusterId: ${cluster.id}
            earlyRenewalSeconds: 0
            groups:
                - system:masters
            ttlSeconds: 0
            user: kubernetes-admin
            zone: ${cluster.zone}
config:
    zone: ch-gva-2  
    version: "" # latest kubernetes version available is used if left empty
    size: 3
    instanceType: standard.medium
    nodepoolSuffix: 0

Ensuite, nous nous connectons au cloud Pulumi (l’endroit où l’état de la stack est stocké).

pulumi login

Ensuite, nous définissons les variables d’environnement pour que Pulumi puisse se connecter à l’API Exoscale.

export EXOSCALE_API_KEY=...
export EXOSCALE_API_SECRET=...

Ensuite, nous initialisons la stack demo.

pulumi stack init demo

Nous pouvons vérifier que la stack existe dans le backend Pulumi.

pulumi stack ls

Pulumi stack

Avant de déployer la stack, nous prévisualisons les ressources qu’elle va créer.

pulumi preview

Cela retourne une sortie similaire à celle qui suit :

Previewing update (demo)

View in Browser (Ctrl+O): https://app.pulumi.com/lucj/sks-template/demo/previews/7b2dedb7-0cb5-42df-9980-5404c1ff09d5

     Type                                 Name                            Plan
 +   pulumi:pulumi:Stack                  sks-template-demo               create
 +   ├─ exoscale:index:SecurityGroup      securityGroup                   create
 +   ├─ exoscale:index:SksCluster         cluster                         create
 +   ├─ exoscale:index:SecurityGroupRule  securityGroupRulesKubelet       create
 +   ├─ exoscale:index:SecurityGroupRule  securityGroupRulesCiliumHCICMP  create
 +   ├─ exoscale:index:SecurityGroupRule  securityGroupRulesNodePorts     create
 +   ├─ exoscale:index:SecurityGroupRule  securityGroupRulesCiliumVXLAN   create
 +   ├─ exoscale:index:SksNodepool        nodepool                        create
 +   ├─ exoscale:index:SecurityGroupRule  securityGroupRulesCiliumHCTCP   create
 +   ├─ exoscale:index:SecurityGroupRule  securityGroupRulesPrometheus    create
 +   └─ exoscale:index:SksKubeconfig      kubeconfig                      create

Outputs:
    kubeConfig: output<string>

Resources:
    + 11 to create

Ensuite, nous déployons la stack, ce qui crée les composants d’infrastructure définis dans Pulumi.yaml, en appliquant la configuration de Pulumi.demo.yaml.

pulumi up
ℹ️
Il faut environ 2 minutes pour que le cluster et les ressources associées soient disponibles.

Portal

Ensuite, nous récupérons le fichier kubeconfig.

pulumi stack output kubeConfig --show-secrets > kubeconfig

Nous configurons notre kubectl local.

export KUBECONFIG=$PWD/kubeconfig

Ensuite, nous pouvons accéder au cluster.

kubectl get nodes
⚠️

Une fois que vous avez terminé le workshop, n’oubliez pas de supprimer le cluster et les ressources associées avec les commandes suivantes :

# Supprimer l'infrastructure
pulumi destroy

# Supprimer la stack du backend Pulumi
pulumi stack rm demo

# Supprimer le fichier kubeconfig
rm $KUBECONFIG