Aller au contenu principal

Le gestionnaire de déploiement kapp"

· 12 minutes de lecture
Stéphane ROBERT
Consultant DevOps

kapp est un outil de la suite Carvel qui permet de gérer le déploiement d'applications sur des clusters Kubernetes.

Les points forts de kapp :

  • Kapp peut fonctionner avec des manifests classiques ou issu de templates Helm ou yyt.
  • Kapp sépare la phase de calcul du changement (diff) de la phase d'application du changement (apply) pour donner aux utilisateurs une visibilité sur ce qui va changer.
  • Kapp suit et fait converger les ressources sur la base d'une étiquette générée unique, évitant ainsi à ses utilisateurs de se soucier du nettoyage des anciennes ressources lors de la mise à jour de l'application
  • Kapp ordonne certaines ressources afin que le serveur d'API Kubernetes puisse les traiter avec succès (par exemple, les CRD et les espaces de noms avant les autres ressources)
  • kapp attends que les ressources soient prêtes avant de considérer que le déploiement s'est fait avec succès.
  • Kapp est gitops ready.

Installation de kapp

Comme pour les autres outils de la suite on installe tout :

wget -O- https://carvel.dev/install.sh > install.sh
sudo bash install.sh
kapp version

kapp version 0.44.0

Succeeded

Utilisation de kapp

Kapp possède plusieurs commandes permettant de gérer les applications d'un cluster kubernetes dont les principales sont : deploy, list, inspect et logs.

Pour obtenir de l'aide il suffit de taper le classique :

kapps [<command>] --help

Toutes les commandes possèdent des alias (deploy : dep ou d) qui sont affichés dans le début de l'aide de chaque commande.

Kapp possède une option --json qui permet d'afficher la ressource sous forme de json. Bien utile pour les ansible users entre autre.

Mon exemple d'application vient des exemples fournis sur le projet de kapp.

Je vais utiliser kind pour créer un cluster et déployer dessus.

Déployer à jour une application

Pour déployer une application on doit lui indiquer comme pour helm un identifiant qui servira à identifier toutes les ressources associées. Pour cela on utilise l'option -a qui vient se placer derrière la commande deploy :

kapp deploy -a simple-app -f config.yml

Target cluster 'https://10.240.0.10:6443' (nodes: master1, 1+)

Changes

Namespace  Name        Kind        Conds.  Age  Op      Op st.  Wait to    Rs  Ri
default    simple-app  Deployment  -       -    create  -       reconcile  -   -
^          simple-app  Service     -       -    create  -       reconcile  -   -

Op:      2 create, 0 delete, 0 update, 0 noop, 0 exists
Wait to: 2 reconcile, 0 delete, 0 noop

Continue? [yN]:

kapp compare les ressources spécifiées dans les fichiers de ressources à ceux qui existent déjà dans le cluster Kubernetes. Une fois l'ensemble de modifications calculé, il offre une option pour l'appliquer.

Continue? [yN]: y

7:01:44AM: ---- applying 2 changes [0/2 done] ----
7:01:44AM: create deployment/simple-app (apps/v1) namespace: default
7:01:44AM: create service/simple-app (v1) namespace: default
7:01:44AM: ---- waiting on 2 changes [0/2 done] ----
7:01:44AM: ok: reconcile service/simple-app (v1) namespace: default
7:01:44AM: ongoing: reconcile deployment/simple-app (apps/v1) namespace: default
7:01:44AM:  ^ Waiting for generation 2 to be observed
7:01:44AM:  L ok: waiting on replicaset/simple-app-765bb9c475 (apps/v1) namespace: default
7:01:44AM:  L ongoing: waiting on pod/simple-app-765bb9c475-fv62b (v1) namespace: default
7:01:44AM:     ^ Pending
7:01:44AM: ---- waiting on 1 changes [1/2 done] ----
7:01:46AM: ongoing: reconcile deployment/simple-app (apps/v1) namespace: default
7:01:46AM:  ^ Waiting for 1 unavailable replicas
7:01:46AM:  L ok: waiting on replicaset/simple-app-765bb9c475 (apps/v1) namespace: default
7:01:46AM:  L ongoing: waiting on pod/simple-app-765bb9c475-fv62b (v1) namespace: default
7:01:46AM:     ^ Pending: ContainerCreating
7:01:54AM: ok: reconcile deployment/simple-app (apps/v1) namespace: default
7:01:54AM: ---- applying complete [2/2 done] ----
7:01:54AM: ---- waiting complete [2/2 done] ----

Succeeded

Vous remarquez que kapp attend bien que les ressources passent au status complete avant de rendre la main avec le code retour associé.

Lister les applications installées

La commande list permet d'afficher toutes les applications déployées avec kapp sur un cluster dans le namespace actuel :

kapp ls
Target cluster 'https://10.240.0.10:6443' (nodes: master1, 1+)

Apps in namespace 'default'

Name        Namespaces  Lcs   Lca
simple-app  default     true  6m

Lcs: Last Change Successful
Lca: Last Change Age

1 apps

Succeeded

Cette commande peut prendre deux options pour afficher les applications d'un namespace : -n <namespace> et -A pour tous les namespaces.

Inspecter les applications

kapp permet d'afficher bien plus d'informations d'une application avec la commande inspect qui possède quelques options bien sympathiques :

kapp inspect -a simple-app --tree
Target cluster 'https://10.240.0.10:6443' (nodes: master1, 1+)

Resources in app 'simple-app'

Namespace  Name                              Kind           Owner    Conds.  Rs  Ri  Age
default    simple-app                        Deployment     kapp     2/2 t   ok  -   14m
default     L simple-app-765bb9c475          ReplicaSet     cluster  -       ok  -   14m
default     L.. simple-app-765bb9c475-fv62b  Pod            cluster  4/4 t   ok  -   14m
default    simple-app                        Service        kapp     -       ok  -   14m
default     L simple-app                     Endpoints      cluster  -       ok  -   14m
default     L simple-app-mrbcg               EndpointSlice  cluster  -       ok  -   14m

Rs: Reconcile state
Ri: Reconcile information

6 resources

Succeeded

Notez qu'il reconnaît aussi les ressources qu'il n'a pas créées directement comme le ReplicaSet et le Endpoints.

Afficher les logs d'une application

Vous allez voir tout de suite le bénéfice d'utiliser kapp pour afficher les logs d'une application. Il existe des alternatives comme stern qui peut produire le même résultat. Kapp s'appuie sur les labels qu'il a posés lors du déploiement pour afficher les logs des différents pods qui compose une application.

Avant on va passer à trois réplicas :

kubectl scale deployment simple-app --replicas 3
deployment.apps/simple-app scaled
Target cluster 'https://127.0.0.1:35919' (nodes: kind-control-plane)

# starting tailing 'simple-app-64bbd6695f-tc25z > simple-app' logs
# starting tailing 'simple-app-64bbd6695f-cw7l8 > simple-app' logs
# starting tailing 'simple-app-64bbd6695f-wdz2p > simple-app' logs
simple-app-64bbd6695f-wdz2p > simple-app | 2022/01/27 07:52:33 Server started
# ending tailing 'simple-app-64bbd6695f-wdz2p > simple-app' logs
simple-app-64bbd6695f-tc25z > simple-app | 2022/01/27 07:57:50 Server started
# ending tailing 'simple-app-64bbd6695f-tc25z > simple-app' logs
simple-app-64bbd6695f-cw7l8 > simple-app | 2022/01/27 07:57:50 Server started
# ending tailing 'simple-app-64bbd6695f-cw7l8 > simple-app' logs

Succeeded

Utilisation de kapp avec des templates

kapp peut utiliser des templates comme source de déclaration. Ici nous allons utiliser ytt, mais ca fonctionne aussi avec helm.

Nous allons utiliser un fichier d'overlay qui vient modifier certaines propriétés du manifest.

#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.subset({"kind": "Deployment"})
---
spec:
  #@overlay/match missing_ok=True
  replicas: 3
kapp deploy -a simple-app -c -f <(ytt template -f config-step-2-template/ -f config-step-2a-overlays/custom-scale.yml)

Target cluster 'https://127.0.0.1:35919' (nodes: kind-control-plane)

@@ update deployment/simple-app (apps/v1) namespace: default @@
  ...
103,103   spec:
104     -   progressDeadlineSeconds: 600
105,104     replicas: 3
106     -   revisionHistoryLimit: 10
107,105     selector:
108,106       matchLabels:
  ...
110,108         simple-app: ""
111     -   strategy:
112     -     rollingUpdate:
113     -       maxSurge: 25%
114     -       maxUnavailable: 25%
115     -     type: RollingUpdate
116,109     template:
117,110       metadata:
118     -       creationTimestamp: null
119,111         labels:
120,112           kapp.k14s.io/app: "1643269818769218079"
  ...
128,120           image: docker.io/dkalinin/k8s-simple-app@sha256:4c8b96d4fffdfae29258d94a22ae4ad1fe36139d47288b8960d9958d1e63a9d0
129     -         imagePullPolicy: IfNotPresent
130,121           name: simple-app
131     -         resources: {}
132     -         terminationMessagePath: /dev/termination-log
133     -         terminationMessagePolicy: File
134     -       dnsPolicy: ClusterFirst
135     -       restartPolicy: Always
136     -       schedulerName: default-scheduler
137     -       securityContext: {}
138     -       terminationGracePeriodSeconds: 30
139,122   status:
140,123     availableReplicas: 3

Changes

Namespace  Name        Kind        Conds.  Age  Op      Op st.  Wait to    Rs  Ri
default    simple-app  Deployment  2/2 t   9m   update  -       reconcile  ok  -

Op:      0 create, 0 delete, 1 update, 0 noop, 0 exists
Wait to: 1 reconcile, 0 delete, 0 noop

Continue? [yN]: y
8:01:10AM: ---- applying 1 changes [0/1 done] ----
8:01:10AM: update deployment/simple-app (apps/v1) namespace: default
8:01:10AM: ---- waiting on 1 changes [0/1 done] ----
8:01:11AM: ongoing: reconcile deployment/simple-app (apps/v1) namespace: default
8:01:11AM:  ^ Waiting for generation 7 to be observed
8:01:11AM:  L ok: waiting on replicaset/simple-app-64bbd6695f (apps/v1) namespace: default
8:01:11AM:  L ok: waiting on replicaset/simple-app-5f8db95765 (apps/v1) namespace: default
8:01:11AM:  L ok: waiting on replicaset/simple-app-549947d777 (apps/v1) namespace: default
8:01:11AM:  L ok: waiting on pod/simple-app-64bbd6695f-wdz2p (v1) namespace: default
8:01:11AM:  L ok: waiting on pod/simple-app-64bbd6695f-tc25z (v1) namespace: default
8:01:11AM:  L ok: waiting on pod/simple-app-64bbd6695f-cw7l8 (v1) namespace: default
8:01:11AM:  L ongoing: waiting on pod/simple-app-549947d777-8rzh8 (v1) namespace: default
8:01:11AM:     ^ Pending
8:01:12AM: ongoing: reconcile deployment/simple-app (apps/v1) namespace: default
8:01:12AM:  ^ Waiting for 1 unavailable replicas
8:01:12AM:  L ok: waiting on replicaset/simple-app-64bbd6695f (apps/v1) namespace: default
8:01:12AM:  L ok: waiting on replicaset/simple-app-5f8db95765 (apps/v1) namespace: default
8:01:12AM:  L ok: waiting on replicaset/simple-app-549947d777 (apps/v1) namespace: default
8:01:12AM:  L ok: waiting on pod/simple-app-64bbd6695f-wdz2p (v1) namespace: default
8:01:12AM:  L ok: waiting on pod/simple-app-64bbd6695f-tc25z (v1) namespace: default
8:01:12AM:  L ok: waiting on pod/simple-app-64bbd6695f-cw7l8 (v1) namespace: default
8:01:12AM:  L ongoing: waiting on pod/simple-app-549947d777-8rzh8 (v1) namespace: default
8:01:12AM:     ^ Pending: ContainerCreating
8:01:13AM: ongoing: reconcile deployment/simple-app (apps/v1) namespace: default
8:01:13AM:  ^ Waiting for 1 unavailable replicas
8:01:13AM:  L ok: waiting on replicaset/simple-app-64bbd6695f (apps/v1) namespace: default
8:01:13AM:  L ok: waiting on replicaset/simple-app-5f8db95765 (apps/v1) namespace: default
8:01:13AM:  L ok: waiting on replicaset/simple-app-549947d777 (apps/v1) namespace: default
8:01:13AM:  L ok: waiting on pod/simple-app-64bbd6695f-wdz2p (v1) namespace: default
8:01:13AM:  L ok: waiting on pod/simple-app-64bbd6695f-tc25z (v1) namespace: default
8:01:13AM:  L ok: waiting on pod/simple-app-64bbd6695f-cw7l8 (v1) namespace: default
8:01:13AM:  L ok: waiting on pod/simple-app-549947d777-8rzh8 (v1) namespace: default
8:01:14AM: ongoing: reconcile deployment/simple-app (apps/v1) namespace: default
8:01:14AM:  ^ Waiting for 1 unavailable replicas
8:01:14AM:  L ok: waiting on replicaset/simple-app-64bbd6695f (apps/v1) namespace: default
8:01:14AM:  L ok: waiting on replicaset/simple-app-5f8db95765 (apps/v1) namespace: default
8:01:14AM:  L ok: waiting on replicaset/simple-app-549947d777 (apps/v1) namespace: default
8:01:14AM:  L ok: waiting on pod/simple-app-64bbd6695f-wdz2p (v1) namespace: default
8:01:14AM:  L ongoing: waiting on pod/simple-app-64bbd6695f-tc25z (v1) namespace: default
8:01:14AM:     ^ Deleting
8:01:14AM:  L ok: waiting on pod/simple-app-64bbd6695f-cw7l8 (v1) namespace: default
8:01:14AM:  L ongoing: waiting on pod/simple-app-549947d777-vz4hx (v1) namespace: default
8:01:14AM:     ^ Pending: ContainerCreating
8:01:14AM:  L ok: waiting on pod/simple-app-549947d777-8rzh8 (v1) namespace: default
8:01:17AM: ongoing: reconcile deployment/simple-app (apps/v1) namespace: default
8:01:17AM:  ^ Waiting for 1 unavailable replicas
8:01:17AM:  L ok: waiting on replicaset/simple-app-64bbd6695f (apps/v1) namespace: default
8:01:17AM:  L ok: waiting on replicaset/simple-app-5f8db95765 (apps/v1) namespace: default
8:01:17AM:  L ok: waiting on replicaset/simple-app-549947d777 (apps/v1) namespace: default
8:01:17AM:  L ok: waiting on pod/simple-app-64bbd6695f-wdz2p (v1) namespace: default
8:01:17AM:  L ongoing: waiting on pod/simple-app-64bbd6695f-tc25z (v1) namespace: default
8:01:17AM:     ^ Deleting
8:01:17AM:  L ongoing: waiting on pod/simple-app-64bbd6695f-cw7l8 (v1) namespace: default
8:01:17AM:     ^ Deleting
8:01:17AM:  L ok: waiting on pod/simple-app-549947d777-vz4hx (v1) namespace: default
8:01:17AM:  L ok: waiting on pod/simple-app-549947d777-8rzh8 (v1) namespace: default
8:01:17AM:  L ongoing: waiting on pod/simple-app-549947d777-7hldh (v1) namespace: default
8:01:17AM:     ^ Pending: ContainerCreating
8:01:20AM: ok: reconcile deployment/simple-app (apps/v1) namespace: default
8:01:20AM: ---- applying complete [1/1 done] ----
8:01:20AM: ---- waiting complete [1/1 done] ----

Succeeded

Vraiment sympa la sortie au format diff qui affiche toutes les modifications qui vont être appliqué.

Afficher l'historique des modifications

Pour afficher l'historique des modifications des applications on utilise la commande app-change list :


kapp app-change list -a simple-app
Target cluster 'https://10.240.0.10:6443' (nodes: master1, 1+)

App changes

Name                     Started At            Finished At           Successful  Description
simple-app-change-k98bc  2022-01-27T09:56:19Z  2022-01-27T09:56:23Z  true        update: Op: 0 create, 0 delete, 1 update, 0 noop, 0 exists / Wait to: 1 reconcile, 0 delete, 0 noop
simple-app-change-l4fwv  2022-01-27T09:05:44Z  2022-01-27T09:05:50Z  true        update: Op: 2 create, 0 delete, 0 update, 0 noop, 0 exists / Wait to: 2 reconcile, 0 delete, 0 noop

2 app changes

Succeeded

Supprimer une application

Pour effacer une application rien de plus simple il suffit d'utiliser la commande delete :

kapp delete -a simple-app
Target cluster 'https://127.0.0.1:35919' (nodes: kind-control-plane)

Changes

Namespace  Name                         Kind           Conds.  Age  Op      Op st.  Wait to  Rs  Ri
default    simple-app                   Deployment     2/2 t   18m  delete  -       delete   ok  -
^          simple-app                   Endpoints      -       18m  -       -       delete   ok  -
^          simple-app                   Service        -       18m  delete  -       delete   ok  -
^          simple-app-549947d777        ReplicaSet     -       7m   -       -       delete   ok  -
^          simple-app-5f8db95765        ReplicaSet     -       18m  -       -       delete   ok  -
^          simple-app-64bbd6695f        ReplicaSet     -       16m  -       -       delete   ok  -
^          simple-app-64bbd6695f-ptkqs  Pod            4/4 t   2m   -       -       delete   ok  -
^          simple-app-64bbd6695f-qlfkl  Pod            4/4 t   2m   -       -       delete   ok  -
^          simple-app-64bbd6695f-v8fhl  Pod            4/4 t   2m   -       -       delete   ok  -
^          simple-app-xt22j             EndpointSlice  -       18m  -       -       delete   ok  -

Op:      0 create, 2 delete, 0 update, 8 noop, 0 exists
Wait to: 0 reconcile, 10 delete, 0 noop

Continue? [yN]: y

8:09:15AM: ---- applying 10 changes [0/10 done] ----
8:09:15AM: noop pod/simple-app-64bbd6695f-qlfkl (v1) namespace: default
8:09:15AM: noop replicaset/simple-app-5f8db95765 (apps/v1) namespace: default
8:09:15AM: noop pod/simple-app-64bbd6695f-ptkqs (v1) namespace: default
8:09:15AM: noop pod/simple-app-64bbd6695f-v8fhl (v1) namespace: default
8:09:15AM: noop replicaset/simple-app-549947d777 (apps/v1) namespace: default
8:09:15AM: noop endpoints/simple-app (v1) namespace: default
8:09:15AM: noop endpointslice/simple-app-xt22j (discovery.k8s.io/v1) namespace: default
8:09:15AM: noop replicaset/simple-app-64bbd6695f (apps/v1) namespace: default
8:09:16AM: delete deployment/simple-app (apps/v1) namespace: default
8:09:16AM: delete service/simple-app (v1) namespace: default
8:09:16AM: ---- waiting on 10 changes [0/10 done] ----
8:09:16AM: ongoing: delete pod/simple-app-64bbd6695f-v8fhl (v1) namespace: default
8:09:16AM: ok: delete service/simple-app (v1) namespace: default
8:09:16AM: ongoing: delete replicaset/simple-app-5f8db95765 (apps/v1) namespace: default
8:09:16AM: ongoing: delete pod/simple-app-64bbd6695f-qlfkl (v1) namespace: default
8:09:16AM: ongoing: delete replicaset/simple-app-549947d777 (apps/v1) namespace: default
8:09:16AM: ongoing: delete pod/simple-app-64bbd6695f-ptkqs (v1) namespace: default
8:09:16AM: ongoing: delete endpointslice/simple-app-xt22j (discovery.k8s.io/v1) namespace: default
8:09:16AM: ongoing: delete replicaset/simple-app-64bbd6695f (apps/v1) namespace: default
8:09:16AM: ok: delete deployment/simple-app (apps/v1) namespace: default
8:09:16AM: ok: delete endpoints/simple-app (v1) namespace: default
8:09:16AM: ---- waiting on 7 changes [3/10 done] ----
8:09:16AM: ok: delete replicaset/simple-app-5f8db95765 (apps/v1) namespace: default
8:09:16AM: ok: delete replicaset/simple-app-549947d777 (apps/v1) namespace: default
8:09:16AM: ok: delete replicaset/simple-app-64bbd6695f (apps/v1) namespace: default
8:09:16AM: ok: delete endpointslice/simple-app-xt22j (discovery.k8s.io/v1) namespace: default
8:09:16AM: ---- waiting on 3 changes [7/10 done] ----
8:09:23AM: ok: delete pod/simple-app-64bbd6695f-ptkqs (v1) namespace: default
8:09:23AM: ok: delete pod/simple-app-64bbd6695f-qlfkl (v1) namespace: default
8:09:23AM: ---- waiting on 1 changes [9/10 done] ----
8:09:24AM: ok: delete pod/simple-app-64bbd6695f-v8fhl (v1) namespace: default
8:09:24AM: ---- applying complete [10/10 done] ----
8:09:24AM: ---- waiting complete [10/10 done] ----

Succeeded

Vous remarquez il détruit toute trace de tout ce qui a été déployé avec kapp.

Conclusion

kapp a vraiment du potentiel et je pense que je vais l'intégrer dans ma liste de pépites. Il manque le moyen de faire un rollback rapidement. Dans un prochain billet nous verrons la partie gitops de kapp.

Source