Créons une tâche de déploiement sur GKE sans plugins, SMS et inscription. Jetons un œil à Jenkins sous le veston

Tout a commencé lorsque le team lead de l'une de nos équipes de développeurs a demandé de mettre en ligne leur nouvelle application, qui avait été récemment conteneurisée, en mode test. Je l'ai fait. Environ vingt minutes plus tard, une demande est arrivée pour mettre à jour l'application car une fonctionnalité très nécessaire avait été ajoutée. J'ai mis à jour. Encore quelques heures plus tard… eh bien, vous devinez ce qui s'est passé ensuite…

Je dois avouer que je suis plutôt paresseux (je l'avais reconnu auparavant, non ?), et étant donné que les team leads ont accès à Jenkins, où se trouve tout notre CI/CD, j'ai pensé : qu'il l'implante lui-même, autant qu'il le souhaite ! Je me suis rappelé une blague : donne à un homme un poisson et il sera plein pendant un jour ; nomme cet homme Satisfait et il le sera toute sa vie. Et je suis parti. fabriquer un job, capable de déployer dans un conteneur Kubernetes une application de n'importe quelle version construite avec succès et de lui transmettre des valeurs quelconques. ENV (mon grand-père, qui était philologue et professeur d'anglais, aurait tourné son doigt autour de son temple et aurait eu un regard très expressif en lisant cette phrase).

Donc, dans cette note, je vais parler de la façon dont j'ai appris :

  1. À mettre à jour dynamiquement des tâches dans Jenkins depuis la tâche elle-même ou depuis d'autres tâches ;
  2. À se connecter à la console cloud (Cloud shell) depuis un nœud avec un agent Jenkins installé ;
  3. À déployer une charge de travail dans Google Kubernetes Engine.


En réalité, j'exagère un peu. Il est supposé que vous avez au moins une partie de votre infrastructure dans le cloud de Google, donc vous êtes un utilisateur de celui-ci et, bien sûr, vous avez un compte GCP. Mais ce n'est pas le sujet de la note.

C'est un de mes rappels. Je n'écris ces notes que dans un seul cas : lorsque j'avais une tâche, que je ne savais pas comment la résoudre au départ, que la solution n'était pas trouvable facilement sur Google, donc je l'ai cherchée par morceaux et à la fin, j'ai résolu la tâche. Et pour que dans le futur, lorsque j'oublierai comment je l'ai fait, je n’aie pas à le chercher à nouveau morceau par morceau et à compiler à nouveau, j'écris ces rappels.

Avertissement : 1. La note a été écrite « pour moi », elle ne prétend pas être un meilleure pratique. Je serais ravi de lire des suggestions sur « mais cela aurait été mieux fait comme ça » dans les commentaires.
2. Si la partie pratique de la note est considérée comme du sel, alors, comme toutes mes notes précédentes, celle-ci est une solution saline faible.

Mise à jour dynamique des paramètres de job dans Jenkins

Je prévois votre question : quel rapport avec la mise à jour dynamique d’un job ? J’ai saisi manuellement la valeur d’un paramètre de chaîne et hop !

Je réponds : je suis vraiment paresseux, je n'aime pas quand on se plaint : Misha, le déploiement échoue, tout est perdu ! On commence à regarder et il y a une erreur dans la valeur d'un paramètre de lancement du job. C'est pourquoi je préfère tout faire de manière aussi antifragile que possible. S'il est possible de priver l'utilisateur de la possibilité de saisir des données directement, en lui offrant à la place une liste de valeurs à choisir, alors j'organise ce choix.

Le plan est le suivant : nous créons un job dans Jenkins, où avant le lancement, il serait possible de choisir une version à partir d'une liste, et de spécifier des valeurs pour les paramètres passés au conteneur via ENV, ensuite, il construit le conteneur et le pousse dans le Container Registry. Puis, de là, le conteneur est lancé dans Kubernetes en tant que workload avec des paramètres spécifiés dans le job.

Nous ne traiterons pas le processus de création et de configuration d'un job dans Jenkins, c'est hors sujet. Nous partirons du principe que le job est prêt. Pour réaliser une liste mise à jour avec des versions, nous avons besoin de deux choses : une liste source déjà existante avec des numéros de version a priori valides et une variable de type Choice parameter dans le job. Dans notre exemple, appelons la variable BUILD_VERSION, nous ne nous attarderons pas dessus. Mais penchons-nous plus en détail sur la liste source.

Les options ne sont pas si nombreuses. Deux me viennent à l'esprit :

  • Utiliser l'API d'accès à distance, que Jenkins propose à ses utilisateurs ;
  • Demander le contenu d’un dossier distant du dépôt (dans notre cas, c'est JFrog Artifactory, ce qui n'est pas essentiel).

Jenkins Remote access API

Selon une excellente tradition établie, je préfère éviter des explications poussées.
Je me permets juste de faire une traduction libre d'un extrait du premier paragraphe de la première page de la documentation de l'API:

Jenkins propose une API pour un accès machine à distance à ses fonctionnalités. L'accès à distance est proposé dans un style similaire à REST. Cela signifie qu'il n'y a pas de point d'entrée unique vers toutes les fonctionnalités, mais à la place, une URL du type ".../api/", où "…" désigne l'objet auquel les fonctionnalités de l'API s'appliquent.

En d'autres termes, si le job de déploiement dont nous parlons actuellement est accessible à l'adresse http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build, les API-points d'accès pour cette tâche sont disponibles à l'adresse http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build/api/

Ensuite, nous avons le choix du format de sortie. Concentrons-nous sur XML, car l'API ne permet une filtration que dans ce cas.

Essayons tout simplement d'obtenir la liste de tous les lancements de la tâche. Nous nous intéresserons uniquement au nom du build (displayName) et à son résultat (result):

http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build/api/xml?tree=allBuilds[displayName,result]

Ça marche ?

Nous allons maintenant filtrer uniquement les lancements qui aboutissent avec le résultat SUCCESS. Utilisons l'argument &exclude et nous passerons en paramètre le chemin jusqu'à la valeur différente de SUCCESS. Oui, oui. La double négation est une affirmation. Excluons tout ce qui ne nous intéresse pas :

http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build/api/xml?tree=allBuilds[displayName,result]&exclude=freeStyleProject/allBuild[result!='SUCCESS']

Capture d'écran de la liste des réussites
Tout a commencé lorsque le responsable d'une de nos équipes de développeurs a demandé, à titre d'essai, de rendre leur nouvelle application accessible, qui avait été récemment conteneurisée.

Et juste pour le plaisir, assurons-nous que le filtre ne nous a pas trompés (les filtres ne mentent jamais !) et affichons la liste des 'non-réussites' :

http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build/api/xml?tree=allBuilds[displayName,result]&exclude=freeStyleProject/allBuild[result='SUCCESS']

Capture d'écran de la liste des non-réussites
Tout a commencé lorsque le responsable d'une de nos équipes de développeurs a demandé, à titre d'essai, de rendre leur nouvelle application accessible, qui avait été récemment conteneurisée.

Liste des versions du dossier sur le serveur distant

Il y a aussi un deuxième moyen d'obtenir la liste des versions. Je l'apprécie même plus que l'appel de l'API de Jenkins. Parce que si l'application a été construite avec succès, cela signifie qu'elle a été empaquetée et mise dans le dépôt du dossier correspondant. En gros, le dépôt est par défaut un stockage pour les versions de travail des applications. Demandons-lui donc quelles versions sont stockées. Nous allons faire un curl, un grep et un awk sur le dossier distant. Si cela intéresse quelqu'un, le one-liner est sous spoiler.

Commande en une ligne
Notez deux choses : je passe dans l'en-tête les identifiants de connexion et je n'ai pas vraiment besoin de toutes les versions du dossier, je sélectionne seulement celles qui ont été créées au cours du mois. Modifiez la commande selon vos réalités et besoins :

curl -H "X-JFrog-Art-Api:VeryLongAPIKey" -s http://arts.myre.po/artifactory/awesomeapp/ | sed 's/a href=//g' | grep "$(date +%b)-$(date +%Y)|$(date +%b --date='-1 month')-$(date +%Y)" | awk '{print $1}' | grep -oP '>K[^/]*'

Configuration des tâches et fichier de configuration de la tâche dans Jenkins

Nous avons compris comment gérer la source de la liste des versions. Maintenant, intégrons la liste obtenue dans la tâche. Pour moi, la solution évidente était d'ajouter une étape dans la tâche de construction de l'application. Une étape qui s'exécuterait en cas de résultat de « succès ».

Ouvrons les paramètres de la tâche de construction et défilons jusqu'en bas. Cliquez sur les boutons : Ajouter une étape de construction -> Étape conditionnelle (unique). Dans les paramètres de l'étape, sélectionnons la condition État actuel de la construction, définissons la valeur SUCCESS, action à exécuter en cas de succès Exécuter une commande shell.

Et maintenant, la partie la plus intéressante. Les configurations de tâches Jenkins sont stockées dans des fichiers. Au format XML. À l'emplacement http://chemin-vers-la-tâche/config.xml Par conséquent, il est possible de télécharger le fichier de configuration, de le modifier comme nécessaire et de le remettre à l'emplacement d'où il a été pris.

N'oubliez pas, comme nous l'avons convenu plus haut, que nous allons créer un paramètre pour la liste des versions. BUILD_VERSION?

Téléchargeons le fichier de configuration et jetons un coup d'œil à l'intérieur. Juste pour nous assurer que le paramètre est en place et qu'il est bien sous la forme désirée.

Capture d'écran sous spoiler.

Votre extrait de config.xml doit être identique. À l'exception près que le contenu de l'élément choices est pour l'instant absent.
Tout a commencé lorsque le responsable d'une de nos équipes de développeurs a demandé, à titre d'essai, de rendre leur nouvelle application accessible, qui avait été récemment conteneurisée.

Vous êtes sûr ? Bon, écrivons le script qui s'exécutera en cas de build réussi.
Le script récupérera la liste des versions, téléchargera le fichier de configuration, écrira à l'endroit nécessaire la liste des versions, puis le remettra à sa place. Oui. C'est exact. Écrire la liste des versions dans le XML à l'endroit où il y a déjà une liste des versions (ce sera à l'avenir, après le premier lancement du script). Je sais, il y a encore des fans acharnés des expressions régulières dans le monde. Je ne fais pas partie de ce groupe. Installez s'il vous plaît xmlstarlet sur la machine où le config sera modifié. Je ne pense pas que ce soit un si grand prix à payer pour éviter d'éditer le XML avec sed.

Sous le spoiler, je fournis le code qui exécute l'ensemble de la séquence décrite ci-dessus.

Nous écrivons dans le config la liste des versions depuis le dossier sur le serveur distant.

#!/bin/bash
############## Скачиваем конфиг
curl -X GET -u username:apiKey http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_k8s/config.xml -o appConfig.xml

############## Удаляем и заново создаем xml-элемент для списка версий
xmlstarlet ed --inplace -d '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]/a[@class="string-array"]' appConfig.xml

xmlstarlet ed --inplace --subnode '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]' --type elem -n a appConfig.xml

xmlstarlet ed --inplace --insert '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]/a' --type attr -n class -v string-array appConfig.xml

############## Читаем в массив список версий из репозитория
readarray -t vers < <( curl -H "X-JFrog-Art-Api:Api:VeryLongAPIKey" -s http://arts.myre.po/artifactory/awesomeapp/ | sed 's/a href=//' | grep "$(date +%b)-$(date +%Y)|$(date +%b --date='-1 month')-$(date +%Y)" | awk '{print $1}' | grep -oP '>K[^/]+' )

############## Пишем массив элемент за элементом в конфиг
printf '%sn' "${vers[@]}" | sort -r | 
                while IFS= read -r line
                do
                    xmlstarlet ed --inplace --subnode '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]/a[@class="string-array"]' --type elem -n string -v "$line" appConfig.xml
                done

############## Кладем конфиг взад
curl -X POST -u username:apiKey http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_k8s/config.xml --data-binary @appConfig.xml

############## Приводим рабочее место в порядок
rm -f appConfig.xml

Si la version qui consiste à obtenir les versions depuis Jenkins vous plaît davantage et que vous êtes aussi paresseux que moi, alors sous le spoiler se trouve le même code, mais la liste provient de Jenkins :

Nous écrivons dans le config la liste des versions depuis Jenkins.
Mais gardez à l'esprit un point : le nom de mon build est composé d'un numéro d'ordre et d'un numéro de version, séparés par deux-points. Par conséquent, awk découpe la partie inutile. Adaptez cette ligne à vos besoins.

#!/bin/bash
############## Скачиваем конфиг
curl -X GET -u username:apiKey http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_k8s/config.xml -o appConfig.xml

############## Удаляем и заново создаем xml-элемент для списка версий
xmlstarlet ed --inplace -d '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]/a[@class="string-array"]' appConfig.xml

xmlstarlet ed --inplace --subnode '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]' --type elem -n a appConfig.xml

xmlstarlet ed --inplace --insert '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]/a' --type attr -n class -v string-array appConfig.xml

############## Пишем в файл список версий из Jenkins
curl -g -X GET -u username:apiKey 'http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build/api/xml?tree=allBuilds[displayName,result]&exclude=freeStyleProject/allBuild[result!=%22SUCCESS%22]&pretty=true' -o builds.xml

############## Читаем в массив список версий из XML
readarray vers < <(xmlstarlet sel -t -v "freeStyleProject/allBuild/displayName" builds.xml | awk -F":" '{print $2}')

############## Пишем массив элемент за элементом в конфиг
printf '%sn' "${vers[@]}" | sort -r | 
                while IFS= read -r line
                do
                    xmlstarlet ed --inplace --subnode '/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.ChoiceParameterDefinition[name="BUILD_VERSION"]/choices[@class="java.util.Arrays$ArrayList"]/a[@class="string-array"]' --type elem -n string -v "$line" appConfig.xml
                done

############## Кладем конфиг взад
curl -X POST -u username:apiKey http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_k8s/config.xml --data-binary @appConfig.xml

############## Приводим рабочее место в порядок
rm -f appConfig.xml

En théorie, si vous avez testé le code basé sur les exemples ci-dessus, vous devriez déjà voir un menu déroulant avec les versions dans la tâche de déploiement. Voilà à quoi cela ressemble sur la capture d'écran sous le spoiler.

Liste des versions correctement remplie.
Tout a commencé lorsque le responsable d'une de nos équipes de développeurs a demandé, à titre d'essai, de rendre leur nouvelle application accessible, qui avait été récemment conteneurisée.

Si tout a fonctionné, collez le script dans Exécuter une commande shell et enregistrez les modifications.

Connexion à Cloud shell.

Les assembleurs se trouvent dans nos conteneurs. Comme moyen de livraison d'applications et gestionnaire de configurations, nous utilisons Ansible. Par conséquent, quand il s'agit d'assembler des conteneurs, trois options viennent à l'esprit : installer Docker dans Docker, installer Docker sur une machine avec Ansible, ou assembler des conteneurs dans la console cloud. Nous avons convenu de ne pas parler des plugins pour Jenkins dans cette note. Vous vous en souvenez ?

J'ai décidé : étant donné que les conteneurs peuvent être assemblés "hors de la boîte" dans la console cloud, pourquoi compliquer les choses ? Keep it clean, n'est-ce pas ? Je veux assembler des conteneurs avec Jenkins dans la console cloud, puis les déployer dans Kubernetes depuis là. D'autant plus qu'au sein de l'infrastructure de Google, les canaux sont très performants, ce qui améliorera la vitesse de déploiement.

Pour se connecter à la console cloud, deux choses sont nécessaires : gcloud et les droits d'accès à Google Cloud API pour l'instance de VM depuis laquelle cette connexion sera établie.

Pour ceux qui prévoient de se connecter depuis un endroit qui n'est pas le cloud de Google
Google autorise la désactivation de l'autorisation interactive dans ses services. Cela permettra de se connecter à la console même depuis une machine à café, tant qu'elle fonctionne sous *nix et dispose d'une console.

S'il y a besoin que j'explique ce sujet plus en détail dans le cadre de cette note, écrivez dans les commentaires. S'il y a suffisamment de votes, je rédigerai une mise à jour sur ce sujet.

La manière la plus simple de donner des permissions est via l'interface web.

  1. Arrêtez l'instance de VM depuis laquelle vous vous connecterez à la console cloud.
  2. Ouvrez les Détails de l'instance et cliquez sur Modifier.
  3. Tout en bas de la page, sélectionnez le champ d'accès de l'instance Accès complet à toutes les Cloud API.

    Capture d'écran
    Tout a commencé lorsque le responsable d'une de nos équipes de développeurs a demandé, à titre d'essai, de rendre leur nouvelle application accessible, qui avait été récemment conteneurisée.

  4. Enregistrez les modifications et démarrez l'instance.

Une fois le chargement de la VM terminé, connectez-vous à celle-ci via SSH et assurez-vous que la connexion se fait sans erreur. Utilisez la commande :

gcloud alpha cloud-shell ssh

Une connexion réussie ressemble à ceci
Tout a commencé lorsque le responsable d'une de nos équipes de développeurs a demandé, à titre d'essai, de rendre leur nouvelle application accessible, qui avait été récemment conteneurisée.

Déploiement dans GKE

Puisque nous nous efforçons de passer complètement à l'IaC (Infrastructure as Code), nos Dockerfiles sont stockés dans Git. D'une part. Et le déploiement dans Kubernetes est décrit par un fichier yaml, qui est utilisé uniquement par cette tâche, qui est en soi également du code. D'autre part. En gros, je veux dire que le plan est le suivant :

  1. Prenez les valeurs des variables BUILD_VERSION et, éventuellement, les valeurs des variables qui seront transmises via ENV.
  2. Téléchargeons le Dockerfile depuis Git.
  3. Générons un fichier yaml pour le déploiement.
  4. Transférons ces deux fichiers par SCP vers la console cloud.
  5. Construisons le conteneur là-bas et publions-le dans le registre de conteneurs.
  6. Appliquons le fichier de déploiement de la charge dans Kubernetes.

Soyons plus précis. Puisque nous avons évoqué ENV, supposons que nous devrons transmettre les valeurs de deux paramètres : PARAM1 et PARAM2. Ajoutons leur définition au déploiement, type — Paramètre chaîne.

Capture d'écran
Tout a commencé lorsque le responsable d'une de nos équipes de développeurs a demandé, à titre d'essai, de rendre leur nouvelle application accessible, qui avait été récemment conteneurisée.

Nous allons générer le yaml par simple redirection echo vers un fichier. Il est supposé, bien sûr, que vous avez dans le Dockerfile PARAM1 et PARAM2, que le nom de la charge sera awesomeapp, et que le conteneur construit avec la version spécifiée est dans Container registry au chemin gcr.io/awesomeapp/awesomeapp-$BUILD_VERSION, où $BUILD_VERSION a bien été sélectionné dans la liste déroulante.

Liste des commandes

touch deploy.yaml
echo "apiVersion: apps/v1" >> deploy.yaml
echo "kind: Deployment" >> deploy.yaml
echo "metadata:" >> deploy.yaml
echo "  name: awesomeapp" >> deploy.yaml
echo "spec:" >> deploy.yaml
echo "  replicas: 1" >> deploy.yaml
echo "  selector:" >> deploy.yaml
echo "    matchLabels:" >> deploy.yaml
echo "      run: awesomeapp" >> deploy.yaml
echo "  template:" >> deploy.yaml
echo "    metadata:" >> deploy.yaml
echo "      labels:" >> deploy.yaml
echo "        run: awesomeapp" >> deploy.yaml
echo "    spec:" >> deploy.yaml
echo "      containers:" >> deploy.yaml
echo "      - name: awesomeapp" >> deploy.yaml
echo "        image: gcr.io/awesomeapp/awesomeapp-$BUILD_VERSION:latest" >> deploy.yaml
echo "        env:" >> deploy.yaml
echo "        - name: PARAM1" >> deploy.yaml
echo "          value: $PARAM1" >> deploy.yaml
echo "        - name: PARAM2" >> deploy.yaml
echo "          value: $PARAM2" >> deploy.yaml

Pour l'agent Jenkins, après connexion via gcloud alpha cloud-shell ssh le mode interactif n'est pas disponible, donc nous transmettons les commandes à la console cloud via le paramètre —command.

Nettoyons le dossier personnel dans la console cloud des anciens Dockerfiles :

gcloud alpha cloud-shell ssh --command="rm -f Dockerfile"

Déposons le Dockerfile fraîchement téléchargé dans le dossier personnel de la console cloud via SCP :

gcloud alpha cloud-shell scp localhost:./Dockerfile cloudshell:~

Assemblons, taguons et publions le conteneur dans le registre de conteneurs :

gcloud alpha cloud-shell ssh --command="docker build -t awesomeapp-$BUILD_VERSION ./ --build-arg BUILD_VERSION=$BUILD_VERSION --no-cache"
gcloud alpha cloud-shell ssh --command="docker tag awesomeapp-$BUILD_VERSION gcr.io/awesomeapp/awesomeapp-$BUILD_VERSION"
gcloud alpha cloud-shell ssh --command="docker push gcr.io/awesomeapp/awesomeapp-$BUILD_VERSION"

Procédons de la même manière avec le fichier de déploiement. Notez que les commandes ci-dessous utilisent des noms fictifs de cluster, où le déploiement a lieu (awsm-cluster) et le nom du projet (awesome-project), où se trouve le cluster.

gcloud alpha cloud-shell ssh --command="rm -f deploy.yaml"
gcloud alpha cloud-shell scp localhost:./deploy.yaml cloudshell:~
gcloud alpha cloud-shell ssh --command="gcloud container clusters get-credentials awsm-cluster --zone us-central1-c --project awesome-project && 
kubectl apply -f deploy.yaml"

Nous lançons la tâche, ouvrons la sortie de la console et espérons voir un déploiement réussi du conteneur.

Capture d'écran
Tout a commencé lorsque le responsable d'une de nos équipes de développeurs a demandé, à titre d'essai, de rendre leur nouvelle application accessible, qui avait été récemment conteneurisée.

Et ensuite, un déploiement réussi du conteneur compilé.

Capture d'écran
Tout a commencé lorsque le responsable d'une de nos équipes de développeurs a demandé, à titre d'essai, de rendre leur nouvelle application accessible, qui avait été récemment conteneurisée.

J'ai délibérément ignoré la configuration. IngressPour une raison simple : une fois configuré avec un nom donné, il restera opérationnel, peu importe combien de déploiements sont effectués avec ce nom. De plus, c'est un peu en dehors du sujet. workload Tous les étapes ci-dessus auraient probablement pu être évitées, et je pourrais simplement installer un plugin pour Jenkins, il y en a des millions. Mais je n'aime pas vraiment les plugins. En fait, je les utilise seulement par désespoir.

Au lieu des conclusions

Et j'aime aussi explorer un nouveau sujet qui m'est inconnu. Le texte ci-dessus est aussi un moyen de partager les découvertes que j'ai faites en résolvant le problème décrit au début. Partager avec ceux qui ne sont pas des experts en DevOps, mais qui s'y intéressent. Si mes trouvailles peuvent aider au moins une personne, je serai satisfait.

Créons une tâche de déploiement dans GKE sans plugins, SMS ou enregistrements. Jetons un coup d'œil à Jenkins sous un autre angle.

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster