Vous vous dites surement qu'avec de l'automatisation et du code pour gagner sa croûte on arrive à planifier des milliers de coups en avance tel Kasparov et que du premier jet, un nouveau projet fonctionne. Alors, je vous le concède, ça peut arriver, mais il arrive aussi que cela soit chaotique et qu'avec un métier pareil on a juste parfois envie de tout cramer car rien ne se passe comme prévu. On a beau retenter avec quelques itérations malheureuses, on se persuade que ça va miraculeusement marcher et non... rien n'y fait, impossible de faire fonctionner la machinerie qu'on a sous les yeux. Et il arrive qu'après plusieurs demi-journée à chercher dans des documentations, sur les internets ou en allant tenter quelques incantations chamaniques*, je passe d'un état fort irritable où un incendie peut se déclarer rien qu'avec mon regard à un état d'euphorique instable avec les larmes qui me coulent sur les joues. Je viens de vivre ça aujourd'hui avec la mise en place d'un Kubernetes agent server pour mon gitlab.

🧄
* Chamaniques ? Non poussez pas, je ne fais pas dans l'ésotérique.
🏗️
Qu'est-ce que gitlab ? Vulgarisons un peu le technique et rendons ça intéressant à lire pour toutes et tous: C'est un dépôt où l'on stocke des fichiers comme on stockerait des affaires, un registre y est tenu et il est possible de remettre l'état du dépôt dans lequel il était quelques jours auparavant. Le programme est git et la suite logiciel qui permet d'héberger chez moi est gitlab. Mes dépôts de fichiers sont donc hébergé chez moi.

Agent spécial Git

KAS, Kubernetes Agent Server, est un composant de Gitlab qui est pré-installé avec gitlab et est actif par défaut, il ne me reste donc en théorie qu'à créer des agents dédiés à mes projets.

Les composants GitLab dont GitLab KAS et sa version.

La documentation est un peu frugale sur la configuration d'un dépôt pour y ajouter des agents, en lisant donc à droite à gauche, il me suffirait d'avoir une liste de configurations d'agents dans un dépôt git, servant de lien entre clusters et runners:

> tree
.
├── .gitlab
│   └── agents
│       ├── myagent-a
│       │   └── config.yaml
│       └── myagent-b
│           └── config.yaml        
└── README.md

Avec ces dossiers d'agents et leurs fichiers de configuration qui délimitent un périmètre je peux connecter gitlab et ses runners à un ou des clusters. Dans la liste des clusters proposé, il suffit d'en ajouter un, on me donne une console et... j'ajoute l'agent... et... le tour est joué ?

Hahaha, naïf que je suis.

KAS les coroutines

c’est à peu prẽs à ce moment que ça commençait à sentir le purin. Pour tester, il suffit de lancer un pipeline dont les instructions sont écrites dans .gitlab-ci.yml à la racine du projet. J’en profite pour appeler le cluster et ses pods, en résulte qu’il m’est impossible d’optemir ce que je souhaite, l’erreur reste vague. Sur le cluster je vérifie l’agent installé via helm et lui me dit qu’il y a effectivement un problème, et il reste très vague.

je ne divulgâche pas tout de suite la solution et je vais détailler les logs pour avoir un peu plus de contexte sur la situation.

Côté agent

{"time":"2024-11-18T11:28:41.253591897Z","level":"ERROR","msg":"Failed to register agent pod. Please make sure the agent version matches the server version","mod_name":"agent_registrar","error":"rpc error: code = Unavailable desc = unavailable"}

Coté pipeline

$ kubectl get pods -n sampleapp
E1117 17:04:57.294399      28 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: an error on the server (\"unknown\") has prevented the request from succeeding"
E1117 17:04:58.807456      28 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: an error on the server (\"unknown\") has prevented the request from succeeding"
E1117 17:05:00.321508      28 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: an error on the server (\"unknown\") has prevented the request from succeeding"
E1117 17:05:01.838095      28 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: an error on the server (\"unknown\") has prevented the request from succeeding"
E1117 17:05:03.354713      28 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: an error on the server (\"unknown\") has prevented the request from succeeding"
Error from server (InternalError): an error on the server ("unknown") has prevented the request from succeeding

Cleaning up project directory and file based variables
00:00
ERROR: Job failed: exit code 1

Clairement le nom de l’erreur n’aide pas mais il est possible d’avoir plus d’informations avec un deuxième pipeline dont on passe en argument de quoi rendre la fonction verbeuse kubectl get nodes -v=10 .

I1117 17:08:02.425666      29 round_trippers.go:466] curl -v -XGET  -H "Accept: application/json;g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList,application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList,application/json" -H "User-Agent: kubectl/v1.31.2 (linux/amd64) kubernetes/5864a46" -H "Authorization: Bearer <masked>" 'https://git.rei.ms/-/kubernetes-agent/k8s-proxy/api?timeout=32s'
I1117 17:08:03.940984      29 round_trippers.go:553] GET https://git.rei.ms/-/kubernetes-agent/k8s-proxy/api?timeout=32s 500 Internal Server Error in 1515 milliseconds
I1117 17:08:03.941038      29 round_trippers.go:570] HTTP Statistics: GetConnection 0 ms ServerProcessing 1514 ms Duration 1515 ms
I1117 17:08:03.941060      29 round_trippers.go:577] Response Headers:
I1117 17:08:03.941086      29 round_trippers.go:580]     Content-Type: application/json
I1117 17:08:03.941106      29 round_trippers.go:580]     Date: Sun, 17 Nov 2024 17:08:03 GMT
I1117 17:08:03.941123      29 round_trippers.go:580]     Server: nginx
I1117 17:08:03.941140      29 round_trippers.go:580]     Strict-Transport-Security: max-age=63072000
I1117 17:08:03.941153      29 round_trippers.go:580]     Content-Length: 292
I1117 17:08:03.941758      29 request.go:1351] Response Body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"GitLab Agent Server: Failed to get allowed agents for CI job token: Get \"https://git.rei.ms/api/v4/job/allowed_agents\": dial tcp 172.19.0.3:443: connect: connection refused","reason":"InternalError","code":500}
E1117 17:08:03.942409      29 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: an error on the server (\"unknown\") has prevented the request from succeeding"
I1117 17:08:03.943610      29 cached_discovery.go:120] skipped caching discovery info due to an error on the server ("unknown") has prevented the request from succeeding
I1117 17:08:03.944048      29 helpers.go:246] server response object: [{
  "metadata": {},
  "status": "Failure",
  "message": "an error on the server (\"unknown\") has prevented the request from succeeding",
  "reason": "InternalError",
  "details": {
    "causes": [
      {
        "reason": "UnexpectedServerResponse",
        "message": "unknown"
      }
    ]
  },
  "code": 500
}]
Error from server (InternalError): an error on the server ("unknown") has prevented the request from succeeding

Cleaning up project directory and file based variables
00:00
ERROR: Job failed: exit code 1

Je ne partage ce qui est le plus intéressant pour comprendre l'erreur. Sachez que depuis un PC tiers sur le réseau (ou en dehors), je peux utiliser le Token avec un curl sans soucis. Alors qu'est-ce qui ne tourne pas rond ?

Regardez un instant l'IP: dial tcp 172.19.0.3:443, j'ai mis du temps avant de le voir. Pourquoi l'IP utilisée est celle du conteneur directement et pas l'ip public ? En gros Gitlab me communique la mauvaise IP je tente d'accéder à quelque chose qui n'existe pas.

La solution réside donc dans mon compose et donner une bonne adresse public afin que lorsque j'utilise KAS ça utilise le bon hostname et pas une IP docker locale.

gitlab_kas['gitlab_address'] = 'http://gitlab.example.com'

💡
Un Cluster Kubernetes est un ensemble de machines appelés nœuds, Kubernetes permet d'exécuter des Pods (petits conteneurs où

Bon, je crois que pour la vulgarisation, on repassera: L'erreur était sans doute un peu trop technique.