Construire un plugin kubectl n’est pas si compliqué, et cela peut vous faire gagner un temps précieux, alors pourquoi passer à côté ?

Ensemble nous donc créer un plugin kubectl qui servira à changer de version du client kubectl lui-même.

Introduction

Qui n’en a jamais eu assez de devoir télécharger la bonne version du client kubectl pour être raccord avec le cluster qu’il gère ?
Surtout quand on permute de cluster et qu’ils sont tous sur des versions différentes.

C’est pour cette raison, simple mais évidente, que nous allons nous empresser de réaliser notre rêve, et ce n’est pas si compliqué. Vous verrez par vous-même !

Nous appellerons notre plugin switch !

Notre plugin kubectl

Fonctionnement

Le client Kubernetes, connu sous le doux nom de kubectl, permet de communiquer avec le serveur « kubectl », appelé API Server, qui représente le cluster Kubernetes lui-même.
La version du client doit être en phase avec celle du serveur, au risque de ne pas pouvoir piloter le cluster correctement, voire apparaître des erreurs (Gloops… moi aussi j’ai le droit à l’erreur).

Intégration

Le client apporte une fonctionnalité intéressante, il favorise et simplifie l’ajout de plugin en autorisant l’exécution de binaire du type kubectl-<mon-plugin>.

L’intégration est bien pensée, et notre binaire donnera nativement naissance à la commande kubectl switch grâce à la notation présentée au-dessus.

Etant donné que le plugin s’appelle swtich, le binaire sera nommé kubectl-switch et la commande d’exécution donnera kubectl switch.

Rassurez-vous, le binaire en question est un simple script bash !

Voici qui est bien et simple pour commencer 🙂

Construction

Gardons en tête que notre plugin servira à changer de version du client.

Nous devons penser à la structure du binaire avant de se lancer dans le code. Nous avons besoin des informations suivantes :

  • La liste exhaustive des paramètres,
  • Les actions réalisées par chacun des paramètres.

Que ce qui est des paramètres, je vous propose les options suivantes :

  • kubectl switch help : Afficher l’aide précieuse du plugin
  • kubectl switch show version : Afficher la version courante du plugin
  • kubectl switch show config : Afficher la configuration actuelle du client
  • kubectl switch version <version> : Permuter la version actuelle du client

Tous les choix de paramètres se feront sur les arguments positionnels apportés au binaire.
En script shell, les arguments sont identifiés par ordre numérique correspondant à la position : $1, $2, … $N pour le N-ième argument.
Et $0 pour le binaire du script appelé.

Afficher d’aide

Tout bon binaire se doit d’avoir un helper pour aider l’utilisateur à bien manier le gouvernail.

Nous allons afficher toutes les commandes apportées par le binaire et l’inclure dans une fonction :

function Usage() {
    echo "kubectl switch <command> <arg>"
    echo "    <command>:"
    echo "        show <arg>      Show core information"
    echo "        version <arg>   Switch client version"
    echo "        help            Show some help for the plugin."
    echo ""
    echo "Command: kubectl show <arg>"
    echo "        version   Show plugin version"
    echo "        config    Show current config"
    echo ""
    echo "Command: kubectl version <arg>"
    echo "    <arg>:"
    echo "        version   Kubernetes client version"
}

Cette fonction sera appelée en toute fin de script, quand l’utilisateur n’aura fait aucun choix valide.

[...] # Sections de code qui suivent
else
    Usage
fi

Afficher la version courante du plugin

Aidons l’utilisateur à y voir plus clair sur la version du plugin.

if [[ "$1" == "show" ]]
then
    if [[ "$2" == "version" ]]
    then
        echo "1.0.0"
        exit 0
    fi

Afficher la configuration actuelle du client

Apportons de la lumiètre à l’utilisateur sur sa configurationactuelle.

if [[ "$1" == "show" ]]
then
    [...] # Section de code exposée précédemment
    elif [[ "$2" == "config" ]]
    then
        echo "KUBECONFIG=${KUBECONFIG}"
        exit 0
    fi

Permuter la version actuelle du client

Voici le coeur du réacteur !

Nous allons nous assurer que l’argument $1 soit égal à version :
if [[ "$1" == "version" ]]

Vérifions l’identification de la version avant d’aller plus loin, sinon le script pourrait tomber dans un cas d’erreur inattendue :
if [[ "$2" =~ v[0-9] ]]

Récupérons le script sur la registry Google et stockons là dans /usr/local/bin sous un nom qui ne rentrera pas en conflit avec l’utilisation courante du client :
alt-kubectl-${VERSION}

Mais avant cela, allons voir si le binaire n’existe pas déjà dans le répertoire, pour éviter de le télécharger à chaque switch :
if [ ! -f /usr/local/bin/alt-kubectl-${VERSION} ]

La procédure est extraite de la documentation officielle : https://kubernetes.io/fr/docs/tasks/tools/install-kubectl/

Enfin, nous pouvons copier/remplacer le binaire ciblé, à savoir kubectl, par une copie du binaire récupéré :
cp -f /usr/local/bin/alt-kubectl-${VERSION} /usr/local/bin/kubectl

Voici la partie du script dans son ensemble :

[...] # Sections de code précédentes
elif [[ "$1" == "version" ]]
then
    if [[ "$2" =~ v[0-9] ]]
    then
        VERSION=$2
        if [ ! -f /usr/local/bin/alt-kubectl-${VERSION} ]
	then
	    if [ "$(curl -sI https://storage.googleapis.com/kubernetes-release/release/${VERSION}/bin/linux/amd64/kubectl | grep ^HTTP | grep 200 )" ]
            then
                echo "Downloading kubectl version ${VERSION}"
                sudo curl -sLo /usr/local/bin/alt-kubectl-${VERSION} "https://storage.googleapis.com/kubernetes-release/release/${VERSION}/bin/linux/amd64/kubectl"
            else
                echo "An error occured on retrieving kubectl binary"
		exit 1
            fi
        fi
        sudo cp -f /usr/local/bin/alt-kubectl-${VERSION} /usr/local/bin/kubectl
        echo "Switching to version ${VERSION}"
        exit 0
    fi
[...] # N'oublions pas le Usage de fin

L’intégralité du code présenté est disponible ici : https://github.com/germainlefebvre4/kubectl-version-switch-plugin

N’oublions pas les droits

Maintenant que notre plugin est écrit, il faut lui accorder les droits d’exécution et le copier au bon emplacement :

sudo chmod +x kubectl-switch
sudo cp kubectl-switch /usr/local/bin

Utilisation

C’est l’heure de vérité !

kubectl switch version v1.18.1
Downloading kubectl version v1.18.1
Switching to version v1.18.1
kubectl version --client
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.1", GitCommit:"7879fc12a63337efff607952a323df90cdc7a335", GitTreeState:"clean", BuildDate:"2020-04-08T17:38:50Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}

Taadaaamm !!! Notre plugin fonctionne du tonnerre ! Reste plus qu’à l’utiliser massivement =)

Un plugin c’est bien, des plugins c’est mieux !

Bien entendu, nous ne sommes pas les seuls à avoir créé un plugin pour kubectl. Pour répertorier les plugins officiels, un utilitaire existe et permet de les télécharger directement : krew.

C’est petit, c’est léger, ça se mange sans fin. Krew récupère et installe des plugins pour vous parmi une liste intéressantes.

La documentation officielle de Krew est disponible par ici :
https://krew.sigs.k8s.io/docs/user-guide/quickstart/

Pour l’installer, suivez le guide (copiez bien les parenthèses de début et fin) :

(
  set -x; cd "$(mktemp -d)" &&
  curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/krew.{tar.gz,yaml}" &&
  tar zxvf krew.tar.gz &&
  KREW=./krew-"$(uname | tr '[:upper:]' '[:lower:]')_amd64" &&
  "$KREW" install --manifest=krew.yaml --archive=krew.tar.gz &&
  "$KREW" update
)

En parcourant la liste, on s’aperçoit vite que les plugins ne manquent pas.

kubectl krew search
NAME DESCRIPTION INSTALLED
access-matrix Show an RBAC access matrix for server resources no
advise-psp Suggests PodSecurityPolicies for cluster. no
apparmor-manager Manage AppArmor profiles for cluster. no
auth-proxy Authentication proxy to a pod or service no
[...]

Installons 2 plugins indispensables :

  • ns : Permet de lister et changer le namespace courant,
  • ctx : Permet de lister et changer le contexte (cluster) Kubernetes courant
kubectl krew install ns
kubectl krew install ctx

Ce qui s’opère de la façon suivante :

kubectl ns
default
kube-node-lease
kube-public
kube-system
kubectl ctx
gke_ilab_europe-west1-b_vault
minikube
opa

On voit vite l’intérêt et la puissance des plugins !

Conclusion

Que vous les créiez ou les utilisiez, les plugins kubectl n’ont maintenant plus de secret pour vous. La seule limite est celle de votre imagination.

Bibliographie