Dans notre article précédent sur les commandes kubectl pour bien gérer votre cluster, je vous avais présenté globalement l’outil ainsi que quelques-unes des commandes kubectl principales.
Aujourd’hui, nous avançons un peu plus dans la jungle des outils DevOps pour découvrir ces créatures fascinantes que sont les commandes kubectl dans leurs formes les plus avancées. En avant ! 🦍
Commandes kubectl avancées les plus courantes
Nous allons voir ici des commandes kubectl légèrement complexes mais qui peuvent être très utiles au quotidien. Dans certains cas, on pourra d’ailleurs configurer un alias pour y accéder plus facilement.
Gestion des secrets dans Kubernetes : kubectl create/get secret
La gestion des secrets est souvent jugée comme une tâche pénible. La raison que j’avance le plus souvent est que les secrets, étant au format base64, demandent à être constamment encodés/décodés. Lorsque notre secret contient plusieurs clés, cela peut rapidement prendre du temps et être source d’erreurs.
Voici deux commandes qui vous permettront de facilement créer, puis lire un secret, sans vous soucier de l’encodage en base64 :
# créer un secret
kubectl create secret generic <NAME> -n <NAMESPACE> --from-env-file <FILENAME> --dry-run=client -o yaml > secret.yaml
# lire et décoder ce secret
kubectl get secrets -n <NAMESPACE> <NAME> -o json | jq '(.data[] |= @base64d).data'
Personnellement, j’ai ajouté deux fonctions dans mon bashrc pour ces commandes dont j’ai régulièrement besoin :
# .bashrc ========================================
alias k=kubectl # un must-have celui-là 😉
# convertit la variable d'environnement $NS en flag de namespace si cette variable existe (utilisé dans les fonctions suivantes)
function ns_flag {
local ns_flag="-n $NS"
if [ -n "$NS" ]; then echo "$ns_flag"; fi
}
# créer un secret k8s depuis un fichier d'environnement
function kmakesec {
k create secret generic $1 --from-env-file $2 $(ns_flag) --dry-run=client -o yaml
}
# récupère un secret k8s au format json et base64-décodé
function kgetsec {
local get_secret="k get secrets $1 $(ns_flag) -o json | jq '(.data[] |= @base64d).data'"
if [ -n "$2" ]; then
eval "$get_secret" | jq -r ".[\"$2\"]"
else
eval "$get_secret -C"
fi
}
# exemples ========================================
$ NS=[NAMESPACE] kmakesec <SECRET_NAME> <ENV_FILE>
$ NS=[NAMESPACE] kgetsec <SECRET_NAME> [SECRET_KEY]
Un petit exemple d’utilisation serait le bienvenu, n’est-ce pas ? 😉
Gestion des labels : kubectl label
Dans certains cas, que ce soit pour lister plus facilement une ressource en particulier, ou pour permettre à un opérateur de fonctionner, il est utile d’appliquer des labels et annotations à certaines ressources.
Bien qu’on puisse éditer ladite ressource pour lui rajouter les labels souhaités manuellement, il est préférable d’utiliser la commande kubectl correspondante : kubectl label <KIND> <NAME> <LABEL_NAME>=<LABEL_VALUE>
. Pour supprimer le label, on utilisera la même commande en préfixant le <LABEL_VALUE>
par un signe moins.
Annotations des ressources Kubernetes : kubectl annotate
On peut de façon similaire annoter une ressource grâce à kubectl annotate <KIND> <NAME> <ANNOTATION_NAME>=<ANNOTATION_VALUE>
. La suppression d’annotation se fait comme pour un label.
Une fois vos ressources labellisées, on peut facilement les filtrer par label, avec par exemple : kubectl get pod -l <LABEL>
pour lister les pods ayant le label donné. On peut également indiquer une valeur pour affiner le filtre.
Ensuite, avec le flag --show-labels
on va pouvoir rajouter une colonne avec tous les labels, ou bien ajouter une colonne avec les valeurs d’un label en particulier avec le flag --label-column <LABEL_NAME>
.
Lancer un conteneur sans yaml avec kubectl run
Il arrive parfois que l’on ait besoin de lancer un conteneur rapidement pour faire un test ou pour effectuer des actions directement depuis l’intérieur du cluster.
Devoir écrire “à la main” un manifeste pour un simple pod peut paraître fastidieux pour certains (moi y compris !). Avec la commande kubctl run
, on va pouvoir lancer un pod en le configurant directement via des flags.
Pour lancer un serveur nginx par exemple, on peut lancer la commande kubectl run nginx --image=nginx --port=80
puis créer un port-forward comme décrit dans le premier article de cette série sur les commandes kubectl afin d’y accéder en local.
On s’en sert parfois chez Enix pour lancer des commandes directement dans un pod du cluster avec une configuration bien précise :
kubectl run --rm -it oonk-tools --image=enix/oonk-tools -n oonk --overrides='{"spec": {"imagePullSecrets": [{"name": "registry-credentials"}]}}' --env OS_AUTH_URL=http://keystone:5000/v3
On retrouve dans cette commande les flags --rm
, -i
et -t
de la commande docker run
. Ils permettent de supprimer le pod une fois terminé et de fournir un terminal interactif à l’utilisateur. On a ensuite l’image et le namespace, puis on termine par un petit bout de json qui permet d’éditer finement les spécifications du pod comme dans un yaml habituel. Enfin, on finit sur une variable d’environnement.
⚠️ Attention ! Dans certains cas, il n’est pas possible d’utiliser kubectl run, par exemple si vous avez besoin d’attacher un volume à un conteneur. En effet kubectl ne fusionne pas la configuration des conteneurs avec celle générée, le flag –image par exemple n’aura aucun effet même s’il reste obligatoire. Dans ce cas, on perd tout l’intérêt de la commande.
Mettre à jour des ressources : kubectl rollout
Kubernetes conserve un historique des versions de ses ressources. Après avoir mis à jour une ressource et vous être aperçu que la nouvelle version ne fonctionne pas, vous pouvez via cet historique récupérer la version précédente dans le cas où vous n’auriez plus le manifeste de cette version : kubectl rollout undo <RESOURCE> <NAME>
. Attention cependant, la commande rollout ne supporte pas toutes les ressources. On l’utilise généralement pour un déploiement ou un daemonset.
Pour rollback sur une version plus ancienne encore, on peut lister l’historique et choisir ensuite son numéro de révision :
kubectl rollout history <RESOURCE> <NAME>
kubectl rollout undo <RESOURCE> <NAME> --to-revision=<REVISION_ID>
On peut également s’en servir pour relancer les pods d’un déploiement proprement puis “watch” son statut jusqu’à complétion :
kubectl rollout restart <RESOURCE> <NAME>
kubectl rollout status -w <RESOURCE> <NAME>
Plongez au coeur de Kubernetes
Dans cette partie, nous allons étudier des commandes plus avancées mais qui ne sont pas forcément autant utilisées. Vous devriez sûrement y trouver quelques commandes utiles.
Options avancées de configuration : kubectl config set/get-context
Si comme moi vous accédez régulièrement à différents clusters, vous vous êtes peut-être déjà demandé comment gérer vos fichiers kubeconfig ?
Par défaut, kubectl va lire le fichier ~/.kube/config. Mais heureusement, kubectl permet de spécifier un fichier de configuration alternatif via la variable d’environnement KUBECONFIG
ou via le paramètre --kubeconfig
. Si vous avez de nombreux clusters, je vous conseille cependant kubie. C’est un outil CLI très pratique qui permet de gérer facilement ses contextes et ses fichiers de configuration.
Si vous préférez avoir un seul fichier kubeconfig et que vous n’utilisez pas kubie, vous avez la possibilité de choisir quel contexte utiliser parmi ceux listés dans votre fichier kubeconfig. On utilisera pour ça la commande kubectl config set-context <CONTEXT_NAME>
. On listera ces contextes via la commande kubectl config get-contexts
. Enfin, pour fusionner plus facilement vos fichiers de configuration, vous pouvez sourcer plusieurs fichiers via les méthodes citées précédemment puis enregistrer la configuration dans un nouveau fichier à utiliser : KUBECONFIG=kubeconfig.1:kubeconfig.2 kubectl config view > kubeconfig.3
.
Kubectl : un client de l’API Kubernetes
Éditer une ressource de manière programmatique et kubectl patch
Dans le fond, le rôle de kubectl n’est que de communiquer avec l’API Kubernetes, c’est pourquoi les développeurs ont intégré la possibilité de construire soi-même des requêtes à l’API Kubernetes grâce au flag --raw
.
Par exemple, pour obtenir la version du serveur on peut faire un kubectl get --raw=/version
, et pour supprimer un deployment un kubectl delete --raw=/apis/apps/v1/namespaces/<NAMESPACE>/deployments/<NAME>
.
Pour finir, vous voudriez peut-être dans certains cas éditer une ressource de manière très précise (pratique dans un script bash par exemple).
Dans ce cas un apply
ne sera peut-être pas la solution idéale. Heureusement, kubectl permet d’éditer ses ressources via un jsonpatch ! Par exemple pour ajouter une valeur dans une config map : kubectl patch cm test --type json -p '[{"op": "add", "path": "/data/<KEY>", "value": "<VALUE>"}]'
.
Vérifier les permissions utilisateur : kubectl auth can-i
Comment savoir ce qu’un utilisateur est autorisé à faire via l’API Kubernetes ? Kubectl offre un mécanisme d’impersonation qui permet d’effectuer une requête en tant qu’un autre utilisateur : kubectl get pods --as-group="<GROUP>" --as="<USER>"
. L’utilisateur peut être un utilisateur classique ou un service account, et le flag --as-group
peut être utilisé plusieurs fois.
Pour tester simplement si un utilisateur à le droit d’exécuter une commande sans la lancer réellement, on utilisera kubectl auth can-i <COMMAND>
avec les flags --as
et optionnellement --as-group
. On peut aussi remplacer la commande à tester par le flag --list
afin de lister toutes les possibilités.
# affiche ”yes” ou “no” avec respectivement l'exit code 0 ou 1
kubectl --as <USER> --as-group="<GROUP1>" --as-group="<GROUP2>" auth can-i delete secrets
# affiche une liste de ressources et de routes avec leur permissions associés
kubectl --as <USER> auth can-i --list
Bonus : récupérer les métadonnées et infos d’un cluster Kubernetes
En bonus, pour terminer ces deux articles sur kubectl, voici quelques commandes qui ne sont pas spécialement avancées mais qui pourraient vous être utiles. Elles permettent d’obtenir de précieuses informations sur le cluster, sa configuration et ses versions.
- kubectl config view : Affiche la configuration courante de kubectl
- kubectl cluster-info : Liste les adresses du control-plane ainsi que des services avec le label kubernetes.io/cluster-service=true ou encore dumper des informations de debugging.
- kubectl api-resources : Liste les types de ressources du cluster
- kubectl api-versions : Liste les versions d’API du cluster
- kubectl version : Affiche la version de kubectl et de l’API server
- kubectl top pods / nodes : Affiche la consommation CPU et RAM de vos pods ou de vos nodes.
Conclusion
Grâce à de nombreuses commandes utilitaires et à la possibilité d’accéder directement à l’API, nous avons vu qu’il était possible de lister, éditer, créer, ou supprimer des ressources d’un cluster Kubernetes très finement. Nous avons également pu tester les autorisation d’accès d’utilisateurs ou de services à l’API, le tout avec différents niveaux de granularité.
Kubectl est un outil relativement simple d’utilisation, mais il est particulièrement puissant car il permet d’effectuer des actions extrêmement précises sur son cluster. Cet outil est nécessaire (indispensable ?) à maîtriser pour tous ceux qui travaillent au quotidien sur des plateformes Kubernetes (ou celles de leurs clients !). En tous les cas, chez Enix, même si on gère du cluster en partie avec des GUI, on s’envoie bien du kubectl dès notre petit-déjeuner !
Ne ratez pas nos prochains articles DevOps et Cloud Native! Suivez Enix sur Twitter!