Trucs et astuces Kubernetes : à propos du développement local et de la téléprésence

Trucs et astuces Kubernetes : à propos du développement local et de la téléprésence

Nous sommes de plus en plus sollicités sur le développement de microservices dans Kubernetes. Les développeurs, en particulier ceux des langages interprétés, souhaitent corriger rapidement le code dans leur IDE préféré et voir le résultat sans attendre la construction/le déploiement - en appuyant simplement sur F5. Et lorsqu'il s'agissait d'une application monolithique, il suffisait d'installer localement une base de données et un serveur web (dans Docker, VirtualBox...), pour ensuite profiter immédiatement du développement. Avec le découpage des monolithes en microservices et l'arrivée de Kubernetes, avec l'apparition de dépendances les uns sur les autres, tout c'est devenu un peu plus difficile. Plus il y a de microservices, plus il y a de problèmes. Pour retrouver le plaisir du développement, il faut monter plus d'un ou deux conteneurs Docker, et parfois même plus d'une douzaine... En général, tout cela peut prendre pas mal de temps, puisqu'il faut aussi le tenir à jour .

À différents moments, nous avons essayé différentes solutions au problème. Et je commencerai par les solutions de contournement accumulées ou simplement les « béquilles ».

1. Béquilles

La plupart des IDE ont la possibilité de modifier le code directement sur le serveur via FTP/SFTP. Cette voie est très évidente et nous avons immédiatement décidé de l'emprunter. Son essence se résume à ce qui suit :

  1. Dans le pod des environnements de développement (dev/review), un conteneur supplémentaire est lancé avec un accès SSH et transmettant la clé SSH publique du développeur qui va valider/déployer l'application.
  2. Au stade d'initialisation (dans le conteneur prepare-app) transférez le code à emptyDirpour avoir accès au code des conteneurs applicatifs et du serveur SSH.

Trucs et astuces Kubernetes : à propos du développement local et de la téléprésence

Pour mieux comprendre la mise en œuvre technique d'un tel schéma, je fournirai des fragments des configurations YAML impliquées dans Kubernetes.

Les configurations

1.1. valeurs.yaml

ssh_pub_key:
  vasya.pupkin: <ssh public key in base64> 

il est vasya.pupkin est la valeur de la variable ${GITLAB_USER_LOGIN}.

1.2. déploiement.yaml

...
{{ if eq .Values.global.debug "yes" }}
      volumes:
      - name: ssh-pub-key
        secret:
          defaultMode: 0600
          secretName: {{ .Chart.Name }}-ssh-pub-key
      - name: app-data
        emptyDir: {}
      initContainers:
      - name: prepare-app
{{ tuple "backend" . | include "werf_container_image" | indent 8 }}
        volumeMounts:
        - name: app-data
          mountPath: /app-data
        command: ["bash", "-c", "cp -ar /app/* /app-data/" ]
{{ end }}
      containers:
{{ if eq .Values.global.debug "yes" }}
      - name: ssh
        image: corbinu/ssh-server
        volumeMounts:
        - name: ssh-pub-key
          readOnly: true
          mountPath: /root/.ssh/authorized_keys
          subPath: authorized_keys
        - name: app-data
          mountPath: /app
        ports:
        - name: ssh
          containerPort: 22
          protocol: TCP
{{ end }}
      - name: backend
        volumeMounts:
{{ if eq .Values.global.debug "yes" }}
        - name: app-data
          mountPath: /app
{{ end }}
        command: ["/usr/sbin/php-fpm7.2", "--fpm-config", "/etc/php/7.2/php-fpm.conf", "-F"]
...

1.3. secret.yaml

{{ if eq .Values.global.debug "yes" }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ .Chart.Name }}-ssh-pub-key
type: Opaque
data:
  authorized_keys: "{{ first (pluck .Values.global.username .Values.ssh_pub_key) }}"
{{ end }}

Touche finale

Après cela, il ne reste plus qu'à transférer variables gitlab-ci.yml requises:

dev:
  stage: deploy
  script:
   - type multiwerf && source <(multiwerf use 1.0 beta)
   - type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
   - werf deploy
     --namespace ${CI_PROJECT_NAME}-stage
     --set "global.env=stage"
     --set "global.git_rev=${CI_COMMIT_SHA}"
     --set "global.debug=yes"
     --set "global.username=${GITLAB_USER_LOGIN}"
 tags:
   - build

Voila : le développeur qui a lancé le déploiement peut se connecter par nom de service (comment accorder en toute sécurité l'accès au cluster, nous avons déjà dit) depuis votre bureau via SFTP et modifiez le code sans attendre qu'il soit livré au cluster.

Il s'agit d'une solution tout à fait efficace, mais du point de vue de la mise en œuvre, elle présente des inconvénients évidents :

  • la nécessité d'affiner la carte Helm, ce qui la rend difficile à lire à l'avenir ;
  • ne peut être utilisé que par la personne qui a déployé le service ;
  • vous devez ensuite vous rappeler de le synchroniser avec le répertoire local avec le code et de le valider dans Git.

2. Téléprésence

Projet La téléprésence est connu depuis assez longtemps, mais nous, comme on dit, "n'avons pas eu le temps de l'essayer sérieusement dans la pratique". Cependant, la demande a fait son travail et nous sommes désormais heureux de partager notre expérience, qui peut être utile aux lecteurs de notre blog - d'autant plus qu'il n'y a pas encore d'autres documents sur la téléprésence sur le hub.

Bref, tout s'est avéré pas si effrayant. Nous avons placé toutes les actions qui nécessitent une exécution de la part du développeur dans un fichier texte de graphique Helm appelé NOTES.txt. Ainsi, après avoir déployé le service sur Kubernetes, le développeur voit les instructions pour lancer l'environnement de développement local dans le journal des tâches GitLab :

!!! Разработка сервиса локально, в составе Kubernetes !!!

* Настройка окружения
* * Должен быть доступ до кластера через VPN
* * На локальном ПК установлен kubectl ( https://kubernetes.io/docs/tasks/tools/install-kubectl/ )
* * Получить config-файл для kubectl (скопировать в ~/.kube/config)
* * На локальном ПК установлен telepresence ( https://www.telepresence.io/reference/install )
* * Должен быть установлен Docker
* * Необходим доступ уровня reporter или выше к репозиторию https://gitlab.site.com/group/app
* * Необходимо залогинится в registry с логином/паролем от GitLab (делается один раз):

#########################################################################
docker login registry.site.com
#########################################################################

* Запуск окружения

#########################################################################
telepresence --namespace {{ .Values.global.env }} --swap-deployment {{ .Chart.Name  }}:backend --mount=/tmp/app --docker-run -v `pwd`:/app -v /tmp/app/var/run/secrets:/var/run/secrets -ti registry.site.com/group/app/backend:v8
#########################################################################

Nous ne nous attarderons pas en détail sur les étapes décrites dans cette notice... à l'exception de la dernière. Que se passe-t-il lors du lancement de Téléprésence ?

Travailler avec la téléprésence

Au démarrage (en utilisant la dernière commande spécifiée dans les instructions ci-dessus), nous définissons :

  • espace de noms dans lequel le microservice s'exécute ;
  • noms du déploiement et du conteneur que nous voulons pénétrer.

Les arguments restants sont facultatifs. Si notre service interagit avec et pour l'API Kubernetes Compte de service créé, nous devons monter des certificats/jetons sur notre bureau. Pour ce faire, utilisez l'option --mount=true (ou --mount=/dst_path), qui montera la racine (/) du conteneur Kubernetes sur notre bureau. Après cela, nous pouvons (en fonction du système d'exploitation et de la manière dont l'application est lancée) utiliser les « clés » du cluster.

Tout d'abord, examinons l'option la plus universelle pour exécuter une application : dans un conteneur Docker. Pour ce faire, nous utiliserons la clé --docker-run et montez le répertoire avec le code dans le conteneur : -v `pwd`:/app

Veuillez noter que cela suppose d'être exécuté à partir du répertoire du projet. Le code de l'application sera monté dans le répertoire /app dans un conteneur.

Suivant: -v /tmp/app/var/run/secrets:/var/run/secrets — pour monter le répertoire avec le certificat/jeton dans un conteneur.

Cette option est enfin suivie de l'image dans laquelle l'application va s'exécuter. NB: Lors de la construction d'une image, vous devez spécifier CMD ou ENTRYPOINT!

Que va-t-il se passer exactement ensuite ?

  • Dans Kubernetes, pour le déploiement spécifié, le nombre de réplicas sera modifié à 0. Au lieu de cela, un nouveau déploiement sera lancé - avec un conteneur de remplacement backend.
  • 2 conteneurs se lanceront sur le bureau : le premier avec la Téléprésence (il proxyera les requêtes depuis/vers Kubernetes), le second avec l'application en cours de développement.
  • Si nous exécutons dans le conteneur avec l'application, alors toutes les variables ENV transférées par Helm lors du déploiement seront disponibles et tous les services seront également disponibles. Il ne reste plus qu'à éditer le code dans votre IDE préféré et profiter du résultat.
  • À la fin du travail, il vous suffit de fermer le terminal dans lequel Telepresence s'exécute (terminez la session avec Ctrl+C) - Les conteneurs Docker s'arrêteront sur le bureau et dans Kubernetes, tout reviendra à son état initial. Il ne reste plus qu'à valider, émettre le MR et le transférer en révision/fusion/… (en fonction de vos workflows).

Si nous ne voulons pas exécuter l'application dans un conteneur Docker - par exemple, nous développons non pas en PHP, mais en Go, tout en la construisant localement - le lancement de Telepresence sera encore plus simple :

telepresence --namespace {{ .Values.global.env }} --swap-deployment {{ .Chart.Name  }}:backend --mount=true

Si l'application accède à l'API Kubernetes, vous devrez monter le répertoire des clés (https://www.telepresence.io/howto/volumes). Il existe un utilitaire pour Linux protéger:

proot -b $TELEPRESENCE_ROOT/var/run/secrets/:/var/run/secrets bash

Après avoir lancé Téléprésence sans l'option --docker-run toutes les variables d'environnement seront disponibles dans le terminal actuel, l'application devra donc y être lancée.

NB: Lorsque vous utilisez, par exemple, PHP, n'oubliez pas de désactiver divers op_cache, apc et autres accélérateurs de développement - sinon la modification du code ne conduira pas au résultat souhaité.

Les résultats de

Le développement local avec Kubernetes est un problème dont la solution croît proportionnellement à la diffusion de cette plateforme. Ayant reçu des demandes pertinentes de la part des développeurs (de nos clients), nous avons commencé à les résoudre avec les premiers moyens disponibles, qui n'ont cependant pas fait leurs preuves sur le long terme. Heureusement, cela est devenu évident non seulement maintenant et pas seulement pour nous, donc des moyens plus adaptés sont déjà apparus dans le monde, et la téléprésence est la plus célèbre d'entre elles (d'ailleurs, il existe aussi échafaudage de Google). Notre expérience d'utilisation n'est pas encore très grande, mais elle nous donne déjà une raison de le recommander à nos « collègues du magasin » - essayez-le !

PS

Autres trucs et astuces de la série K8s :

Source: habr.com

Ajouter un commentaire