We creëren een implementatietaak in GKE zonder plug-ins, sms of registratie. Laten we een kijkje nemen onder Jenkins' jasje

Het begon allemaal toen de teamleider van een van onze ontwikkelingsteams ons vroeg om hun nieuwe applicatie, die de dag ervoor in containers was geplaatst, te testen. Ik heb het gepost. Na ongeveer 20 minuten kwam er een verzoek om de applicatie te updaten, omdat daar iets heel noodzakelijks was toegevoegd. Ik heb verlengd. Na nog een paar uur... nou ja, je kunt wel raden wat er daarna gebeurde...

Ik moet toegeven dat ik nogal lui ben (heb ik dit niet eerder toegegeven? Nee?), en gezien het feit dat teamleiders toegang hebben tot Jenkins, waarin we allemaal CI/CD hebben, dacht ik: laat hem maar inzetten als zoveel als hij wil! Ik herinnerde me een grap: geef een man een vis en hij heeft een dag te eten; noem iemand Fed en hij zal zijn hele leven Fed zijn. En ging speel trucjes op het werk, die een container met de toepassing van elke succesvol gebouwde versie in Kuber zou kunnen inzetten en alle waarden ernaar zou kunnen overbrengen ENV (mijn grootvader, een filoloog en vroeger leraar Engels, draaide nu met zijn vinger naar zijn slaap en keek me heel expressief aan na het lezen van deze zin).

Dus in deze notitie zal ik je vertellen hoe ik het heb geleerd:

  1. Werk taken in Jenkins dynamisch bij vanuit de taak zelf of vanuit andere taken;
  2. Maak verbinding met de cloudconsole (Cloud shell) vanaf een knooppunt waarop de Jenkins-agent is geïnstalleerd;
  3. Implementeer de werklast naar Google Kubernetes Engine.


Eigenlijk ben ik natuurlijk een beetje onoprecht. Er wordt aangenomen dat u ten minste een deel van de infrastructuur in de Google-cloud heeft, dat u daarom de gebruiker ervan bent en uiteraard een GCP-account heeft. Maar daar gaat deze nota niet over.

Dit is mijn volgende spiekbriefje. Dergelijke aantekeningen wil ik slechts in één geval schrijven: ik werd geconfronteerd met een probleem, ik wist aanvankelijk niet hoe ik het moest oplossen, de oplossing was niet kant-en-klaar gegoogled, dus ik googlede het in delen en loste uiteindelijk het probleem op. En zodat ik in de toekomst, als ik vergeet hoe ik het deed, niet alles stukje bij beetje opnieuw hoef te googlen en samen te stellen, schrijf ik mezelf zulke spiekbriefjes.

Disclaimer: 1. Het briefje is geschreven “voor mezelf”, voor de rol best practice is niet van toepassing. Ik ben blij om de opties “het zou beter zijn geweest om het op deze manier te doen” in de reacties te lezen.
2. Als het toegepaste deel van het biljet als zout wordt beschouwd, dan is dit, net als al mijn eerdere aantekeningen, een zwakke zoutoplossing.

Dynamisch bijwerken van taakinstellingen in Jenkins

Ik voorzie uw vraag: wat heeft het dynamisch bijwerken van vacatures ermee te maken? Voer de waarde van de stringparameter handmatig in en u kunt aan de slag!

Ik antwoord: ik ben echt lui, ik vind het niet leuk als ze klagen: Misha, de implementatie crasht, alles is weg! Je begint te zoeken en er zit een typefout in de waarde van een parameter voor het starten van een taak. Daarom doe ik het liefst alles zo efficiënt mogelijk. Als het mogelijk is om te voorkomen dat de gebruiker gegevens rechtstreeks invoert door in plaats daarvan een lijst met waarden te geven waaruit hij kan kiezen, dan organiseer ik de selectie.

Het plan is dit: we creëren een taak in Jenkins, waarin we, voordat we lanceren, een versie uit de lijst kunnen selecteren, waarden kunnen specificeren voor parameters die via ENV, waarna de container wordt verzameld en naar het containerregister wordt geduwd. Vervolgens wordt de container in Cuber as gelanceerd werkdruk met de parameters die in de taak zijn opgegeven.

We zullen het proces van het creëren en opzetten van een baan bij Jenkins niet overwegen, dit is buiten het onderwerp. We gaan ervan uit dat de taak gereed is. Om een ​​bijgewerkte lijst met versies te implementeren, hebben we twee dingen nodig: een bestaande bronlijst met a priori geldige versienummers en een variabele zoals Keuzeparameter bij de taak. In ons voorbeeld laat u de variabele een naam hebben BUILD_VERSION, we zullen er niet in detail op ingaan. Maar laten we de bronnenlijst eens nader bekijken.

Er zijn niet zoveel opties. Twee dingen kwamen meteen in me op:

  • Gebruik de Remote Access API die Jenkins aan zijn gebruikers aanbiedt;
  • Vraag de inhoud van de externe repositorymap op (in ons geval is dit JFrog Artifactory, wat niet belangrijk is).

Jenkins API voor externe toegang

Volgens de gevestigde uitstekende traditie zou ik lange uitleg liever vermijden.
Ik sta mezelf alleen een vrije vertaling toe van een stukje van de eerste alinea eerste pagina met API-documentatie:

Jenkins biedt een API voor machinaal leesbare toegang op afstand tot de functionaliteit ervan. <…> Toegang op afstand wordt aangeboden in een REST-achtige stijl. Dit betekent dat er geen enkel toegangspunt is voor alle functies, maar in plaats daarvan een URL zoals ".../api/", Waar "..." betekent het object waarop de API-mogelijkheden worden toegepast.

Met andere woorden, als de implementatietaak waar we het momenteel over hebben beschikbaar is op http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build, dan zijn de API-fluitjes voor deze taak beschikbaar op http://jenkins.mybuild.er/view/AweSomeApp/job/AweSomeApp_build/api/

Vervolgens hebben we een keuze in welke vorm we de uitvoer willen ontvangen. Laten we ons concentreren op XML, omdat de API in dit geval alleen filteren toestaat.

Laten we proberen een lijst te krijgen van alle taakuitvoeringen. We zijn alleen geïnteresseerd in de merknaam (Weergavenaam) en het resultaat ervan (resultaat):

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

Het bleek?

Laten we nu alleen die runs filteren die het resultaat opleveren SUCCES. Laten we het argument gebruiken &uitsluiten en als parameter zullen we het pad doorgeven naar een waarde die niet gelijk is aan SUCCES. Ja Ja. Een dubbele ontkenning is een verklaring. We sluiten alles uit wat ons niet interesseert:

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

Screenshot van de lijst met succesvolle
We creëren een implementatietaak in GKE zonder plug-ins, sms of registratie. Laten we een kijkje nemen onder Jenkins' jasje

Laten we, voor de lol, ervoor zorgen dat het filter ons niet heeft misleid (filters liegen nooit!) en een lijst met ‘niet-succesvolle’ filters weergeven:

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

Screenshot van de lijst met niet-succesvolle projecten
We creëren een implementatietaak in GKE zonder plug-ins, sms of registratie. Laten we een kijkje nemen onder Jenkins' jasje

Lijst met versies uit een map op een externe server

Er is een tweede manier om een ​​lijst met versies te krijgen. Ik vind het zelfs leuker dan toegang krijgen tot de Jenkins API. Nou ja, want als de applicatie met succes is gebouwd, betekent dit dat deze is verpakt en in de repository in de juiste map is geplaatst. Een repository is bijvoorbeeld de standaardopslag van werkende versies van applicaties. Leuk vinden. Laten we hem vragen welke versies er in opslag zijn. We zullen de externe map krullen, grep en awk. Als iemand geïnteresseerd is in de oneliner, dan staat deze onder de spoiler.

Eén regelopdracht
Let op twee dingen: ik geef de verbindingsgegevens door in de header en ik heb niet alle versies uit de map nodig, en ik selecteer alleen de versies die binnen een maand zijn gemaakt. Bewerk de opdracht zodat deze bij uw realiteit en behoeften past:

curl -H "X-JFrog-Art-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[^/]+' )

Taken en taakconfiguratiebestand instellen in Jenkins

We hebben de bron van de lijst met versies ontdekt. Laten we nu de resulterende lijst in de taak opnemen. Voor mij was de voor de hand liggende oplossing het toevoegen van een stap aan de applicatiebouwtaak. De stap die zou worden uitgevoerd als het resultaat 'succes' was.

Open de montagetaakinstellingen en scroll helemaal naar beneden. Klik op de knoppen: Bouwstap toevoegen -> Voorwaardelijke stap (enkel). Selecteer de voorwaarde in de stapinstellingen Huidige buildstatus, stel de waarde in SUCCES, de actie die moet worden uitgevoerd als deze succesvol is Voer de shell-opdracht uit.

En nu het leuke gedeelte. Jenkins slaat taakconfiguraties op in bestanden. In XML-formaat. Onderweg http://путь-до-задания/config.xml Dienovereenkomstig kunt u het configuratiebestand downloaden, indien nodig bewerken en terugplaatsen waar u het heeft gekregen.

Vergeet niet dat we hierboven hebben afgesproken dat we een parameter voor de lijst met versies zullen maken BUILD_VERSION?

Laten we het configuratiebestand downloaden en er een kijkje in nemen. Gewoon om er zeker van te zijn dat de parameter aanwezig is en van het gewenste type is.

Screenshot onder spoiler.

Uw config.xml-fragment zou er hetzelfde uit moeten zien. Alleen ontbreekt de inhoud van het keuzes-element nog
We creëren een implementatietaak in GKE zonder plug-ins, sms of registratie. Laten we een kijkje nemen onder Jenkins' jasje

Weet je het zeker? Dat is alles, laten we een script schrijven dat zal worden uitgevoerd als de build succesvol is.
Het script ontvangt een lijst met versies, downloadt het configuratiebestand, schrijft de lijst met versies erin op de plaats die we nodig hebben en plaatst het vervolgens terug. Ja. Dat is juist. Schrijf een lijst met versies in XML op de plaats waar al een lijst met versies bestaat (dit zal in de toekomst zijn, na de eerste lancering van het script). Ik weet dat er nog steeds fervente fans van reguliere expressies in de wereld zijn. Ik behoor niet tot hen. Installeer alstublieft xmlstarler naar de machine waar de configuratie zal worden bewerkt. Het lijkt mij dat dit niet zo'n hoge prijs is om te voorkomen dat XML met sed wordt bewerkt.

Onder de spoiler presenteer ik de code die de bovenstaande reeks in zijn geheel uitvoert.

Schrijf een lijst met versies vanuit een map op de externe server naar het bestand config

#!/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

Als je de voorkeur geeft aan de optie om versies van Jenkins te krijgen en je bent net zo lui als ik, dan staat onder de spoiler dezelfde code, maar een lijst van Jenkins:

Schrijf een lijst met versies van Jenkins naar het bestand config
Houd hier rekening mee: mijn assembly-naam bestaat uit een volgnummer en een versienummer, gescheiden door een dubbele punt. Dienovereenkomstig snijdt awk het onnodige deel af. Voor uzelf kunt u deze lijn aanpassen aan uw behoeften.

#!/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

Als je de code hebt getest die is geschreven op basis van de bovenstaande voorbeelden, zou je in theorie in de implementatietaak al een vervolgkeuzelijst met versies moeten hebben. Het is zoals in de schermafbeelding onder de spoiler.

Correct ingevulde versielijst
We creëren een implementatietaak in GKE zonder plug-ins, sms of registratie. Laten we een kijkje nemen onder Jenkins' jasje

Als alles werkte, kopieer en plak dan het script in Voer de shell-opdracht uit en wijzigingen opslaan.

Verbinding maken met Cloudshell

Wij beschikken over verzamelaars in containers. We gebruiken Ansible als onze applicatieleveringstool en configuratiemanager. Als het gaat om het bouwen van containers, denk ik dus aan drie opties: installeer Docker in Docker, installeer Docker op een machine waarop Ansible draait, of bouw containers in een cloudconsole. We hebben afgesproken om in dit artikel te zwijgen over plug-ins voor Jenkins. Herinneren?

Ik besloot: nou, aangezien containers “out of the box” kunnen worden verzameld in de cloudconsole, waarom zou je je dan druk maken? Houd het schoon, toch? Ik wil Jenkins-containers verzamelen in de cloudconsole en ze van daaruit in de cuber lanceren. Bovendien beschikt Google over zeer rijke kanalen binnen zijn infrastructuur, wat een gunstig effect zal hebben op de snelheid van implementatie.

Om verbinding te maken met de cloudconsole heb je twee dingen nodig: gwolk en toegangsrechten tot Google Cloud API voor de VM-instantie waarmee dezelfde verbinding tot stand wordt gebracht.

Voor degenen die van plan zijn om helemaal geen verbinding te maken vanuit de Google-cloud
Google biedt de mogelijkheid om interactieve autorisatie in zijn diensten uit te schakelen. Hierdoor kunt u zelfs vanaf een koffiezetapparaat verbinding maken met de console, als deze op *nix draait en zelf een console heeft.

Als het nodig is dat ik deze kwestie in het kader van deze nota gedetailleerder bespreek, schrijf dat dan in de commentaren. Als we genoeg stemmen krijgen, zal ik een update over dit onderwerp schrijven.

De eenvoudigste manier om rechten te verlenen is via de webinterface.

  1. Stop de VM-instantie van waaruit u vervolgens verbinding maakt met de cloudconsole.
  2. Open Instantiedetails en klik amenderen.
  3. Selecteer helemaal onderaan de pagina het toegangsbereik van de instantie Volledige toegang tot alle Cloud API's.

    Screenshot
    We creëren een implementatietaak in GKE zonder plug-ins, sms of registratie. Laten we een kijkje nemen onder Jenkins' jasje

  4. Sla uw wijzigingen op en start de instantie.

Zodra de VM klaar is met laden, maakt u er verbinding mee via SSH en zorgt u ervoor dat de verbinding zonder fouten plaatsvindt. Gebruik het commando:

gcloud alpha cloud-shell ssh

Een succesvolle verbinding ziet er ongeveer zo uit
We creëren een implementatietaak in GKE zonder plug-ins, sms of registratie. Laten we een kijkje nemen onder Jenkins' jasje

Implementeren naar GKE

Omdat we er op alle mogelijke manieren naar streven om volledig over te stappen op IaC (Infrastucture as a Code), worden onze dockerbestanden opgeslagen in Git. Dit is aan de ene kant. En de implementatie in kubernetes wordt beschreven door een yaml-bestand, dat alleen door deze taak wordt gebruikt, en dat zelf ook op code lijkt. Dit komt van de andere kant. Over het algemeen bedoel ik dat het plan dit is:

  1. We nemen de waarden van de variabelen BUILD_VERSION en eventueel de waarden van de variabelen die worden doorgegeven ENV.
  2. Download het dockerbestand van Git.
  3. Genereer yaml voor implementatie.
  4. We uploaden beide bestanden via scp naar de cloudconsole.
  5. We bouwen daar een container en pushen deze in het Container-register
  6. We passen het belastingimplementatiebestand toe op de cuber.

Laten we specifieker zijn. Ooit begonnen we erover te praten ENVStel dan dat we de waarden van twee parameters moeten doorgeven: PARAM1 и PARAM2. We voegen hun taak toe voor implementatie, type - Tekenreeksparameter.

Screenshot
We creëren een implementatietaak in GKE zonder plug-ins, sms of registratie. Laten we een kijkje nemen onder Jenkins' jasje

We zullen yaml genereren met een eenvoudige omleiding echo archiveren. Er wordt uiteraard van uitgegaan dat je dit in je dockerfile hebt staan PARAM1 и PARAM2dat de ladingsnaam zal zijn geweldige app, en de geassembleerde container met de toepassing van de opgegeven versie ligt erin Containerregister onderweg gcr.io/awesomeapp/awesomeapp-$BUILD_VERSIONWaar $BUILD_VERSION is zojuist geselecteerd in de vervolgkeuzelijst.

Teamlijst

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

Jenkins-agent na verbinding met behulp van gcloud alpha cloud-shell ssh de interactieve modus is niet beschikbaar, dus sturen we opdrachten naar de cloudconsole met behulp van de parameter --commando.

We ruimen de thuismap in de cloudconsole op van het oude dockerbestand:

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

Plaats het zojuist gedownloade dockerbestand in de thuismap van de cloudconsole met behulp van scp:

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

Wij verzamelen, taggen en pushen de container naar het Containerregister:

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"

Hetzelfde doen we met het implementatiebestand. Houd er rekening mee dat de onderstaande opdrachten fictieve namen gebruiken van het cluster waar de implementatie plaatsvindt (awsm-cluster) en projectnaam (geweldig project), waar het cluster zich bevindt.

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"

We voeren de taak uit, openen de console-uitvoer en hopen de succesvolle montage van de container te zien.

Screenshot
We creëren een implementatietaak in GKE zonder plug-ins, sms of registratie. Laten we een kijkje nemen onder Jenkins' jasje

En dan de succesvolle inzet van de geassembleerde container

Screenshot
We creëren een implementatietaak in GKE zonder plug-ins, sms of registratie. Laten we een kijkje nemen onder Jenkins' jasje

Ik heb bewust de instelling genegeerd Ingress. Om één simpele reden: als je het eenmaal hebt ingesteld werkdruk met een bepaalde naam blijft deze operationeel, ongeacht hoeveel implementaties je met deze naam uitvoert. Over het algemeen valt dit een beetje buiten het bereik van de geschiedenis.

In plaats van conclusies

Alle bovenstaande stappen hadden waarschijnlijk niet kunnen worden uitgevoerd, maar eenvoudigweg een plug-in voor Jenkins geïnstalleerd, hun muuulion. Maar om de een of andere reden houd ik niet van plug-ins. Nou ja, preciezer gezegd: ik gebruik ze alleen uit wanhoop.

En ik vind het gewoon leuk om een ​​nieuw onderwerp voor mij op te pikken. De bovenstaande tekst is ook een manier om de bevindingen te delen die ik heb gedaan bij het oplossen van het probleem dat aan het begin werd beschreven. Deel met degenen die, net als hij, helemaal geen verschrikkelijke wolf zijn in devops. Als mijn bevindingen tenminste iemand helpen, zal ik blij zijn.

Bron: www.habr.com

Voeg een reactie