I en tid då AI-assisterad programmering utvecklas snabbt går det inte att överskatta vikten av robusta DevOps-metoder. I det här blogginlägget visar jag hur AI kan användas effektivt för att bygga och förbättra CI/CD-pipelines, samtidigt som jag belyser att mänsklig expertis fortfarande är avgörande trots AI:s stora framsteg.
Alex Jantunen
Alex is an experienced software architect specializing in solving complex problems and optimizing CI/CD pipelines. He is particularly skilled in microservices, backend, and DevOps.
Att etablera en stabil DevOps-grund är inte längre ett projekt som tar månader. Med rätt arbetssätt och verktyg kan, och bör, även små projekt ha en fungerande DevOps-struktur på plats inom dagar eller veckor. Låt oss nu fokusera på grunderna i CI/CD och börja med Git-workflowet.
Git-workflow: Grunden för bra CI/CD
Som vi alla vet är tydliga och väldokumenterade arbetssätt för Git avgörande för alla framgångsrika utvecklingsprojekt, särskilt inom DevOps. Här visar jag hur du kan skapa ett från grunden med hjälp av ChatGPT 4. Du kan testa resultatet genom att använda exakt samma prompts som jag har använt här (ChatGPT 4 krävs).
Prompt nr 1
Den första prompten fungerar vanligtvis som en introduktion till ämnet. Med det här arbetssättet kan du se det första svaret och förstå vilken riktning diskussionen tar. En enskild prompt räcker sällan. Läs vidare för att se hur jag styr diskussionen vidare. Min första prompt är följande:
Ge mig en grundläggande Git-workflow så att jag senare kan implementera pipelines för Continuous Integration och Continuous Deployment ovanpå arbetssätten i workflowet
GPT-svar
Att skapa en stabil grund för Git-workflowet är avgörande för att effektivt implementera pipelines för Continuous Integration (CI) och Continuous Deployment (CD). Här är ett förslag på ett grundläggande workflow som du kan använda som utgångspunkt: ...
Strategi för branches:
Main-branch: Detta är den primära branchen, där källkoden i HEAD alltid motsvarar ett produktionsklart tillstånd.
Develop-branch: Denna branch fungerar som en integrationsbranch för funktioner. Den innehåller alltid de senaste levererade utvecklingsändringarna inför nästa release.
Feature-branches: Skapa dessa branches när du börjar arbeta med en ny funktion. Utgå från ”develop” och mergea tillbaka till ”develop” när funktionen är klar.
Release-branches: Utgå från ”develop” när du är redo att förbereda en ny produktionsrelease. Det gör att ett team kan finslipa den aktuella releasen medan ett annat team fortsätter arbeta med funktioner för nästa release.
Hotfix-branches: Dessa branches används för att snabbt åtgärda produktionsreleaser. De liknar release- och feature-branches, men utgår från ”main” och mergeas in i både ”main” och ”develop”.
Continuous Integration (CI):
Konfigurera en CI-pipeline som kör automatiserade tester och andra kontroller, till exempel linting, varje gång en ny commit pushas till en branch – särskilt till ”develop” och feature-branches.
Continuous Deployment (CD):
När CI-pipelinen har godkänts och ändringarna har mergeats in i main-branchen kan du automatiskt driftsätta till produktion, om din konfiguration tillåter det.
För miljöer med större kontroll kan du välja att utlösa driftsättningar manuellt från main-branchen.
Versionsmärkning:
Efter varje release märker du koden i main-branchen med ett versionsnummer.
Dokumentation:
Håll projektets dokumentation uppdaterad. Det omfattar inte bara kodens dokumentation utan även era workflow- och pipelineprocesser.
Dessutom finns avsnitt om riktlinjer för commits, kodgranskning och merging, men vi fokuserar inte på dem i det här blogginlägget, även om de är viktiga.
Slutsats om att använda en grundläggande Git-workflow
Till och med AI verkar betona vikten av Git-workflows. Den föreslår separata utvecklings- och releasegrenar, vilket är en bra strategi när den implementeras korrekt. Men för att illustrera detta visar jag ett mer förenklat workflow som kan vara mer optimalt.
Observera den viktiga aspekten: Dokumentera ditt workflow och din pipeline! Här verkar AI:s tankegång vara väl genomtänkt och oftast bättre än verkligheten.
Tydlig kommunikation kring dessa ämnen och retrospektiv säkerställer en fortsatt bra Developer Experience (DevEx).
Prompt nr 2
Nu när vi har fått det första svaret och ChatGPT har vår diskussionshistorik sparad för framtida promptar planerar jag att be om mer specifika detaljer. Det är lämpligt att utvärdera svaret efter den första prompten och efter varje efterföljande svar, samt fördjupa sig i nya ämnen som uppstår vid behov.
Först därefter bör du gå vidare till nästa prompt för att undvika att störa chattsessionen, vilket lätt kan leda till oönskade resultat med stora språkmodeller (LLM:er).
Gör workflowet enklare och ta bort develop- och releasegrenarna. För dessa kommer jag att använda Git-taggar.
GPT-svar
Absolut! Att förenkla Git-workflowet genom att ta bort develop- och releasegrenarna och använda Git-taggar i stället kan göra processen smidigare, särskilt för mindre team eller projekt. Här är en reviderad version av workflowet:
Huvudgren:
Detta är din primära och enda långlivade gren. Huvudgrenen representerar den produktionsklara versionen av din kod.
Alla funktioner, buggfixar och akutfixar mergas direkt in i denna gren.
Funktionsgrenar:
Skapa en funktionsgren varje gång du börjar arbeta med en ny funktion eller en buggfix.
Utgå från main och merga tillbaka till main när arbetet är klart och testat.
Namnkonventionen för funktionsgrenar kan exempelvis vara
feature/<feature-name>ellerbugfix/<bug-name>.
Git-taggar för releaser:
När du är redo att släppa en ny version använder du Git-taggar på huvudgrenen.
Namnge dina taggar enligt semantisk versionshantering (t.ex. v1.0.0, v1.0.1) för att hålla koll på olika releaser.
Taggar kan också användas för att vid behov utlösa specifika CI/CD-åtgärder.
Continuous Deployment (CD):
Om projektets uppsättning tillåter det kan du konfigurera CD så att huvudgrenen automatiskt driftsätts i produktion efter godkända CI-kontroller.
För mer kontrollerade miljöer kan du välja att manuellt driftsätta taggade versioner.
De övriga delarna är mycket lika de tidigare och behöver inte upprepas här.
Slutsats om att förenkla workflowet och ta bort develop- och releasegrenarna
Okej, det här ser nu ut som det jag bad om. En oro uppstår dock när GPT föreslår att main-branchen automatiskt driftsätts till produktion efter CI.
Vi vet alla att vi, för vårt eget förstånds och systemens tillförlitlighets skull, definitivt behöver produktionsliknande miljöer, till exempel staging, för ordentlig kvalitetssäkring (QA).
Det är avgörande att köra automatiserade regressionstester i produktionsliknande miljöer efter varje förändring. Det omfattar inte bara kodändringar i produkten utan även ändringar relaterade till infrastruktur (IaC), pipelines och mer.
Prompt #3
För Continuous Deployment vill jag automatiskt driftsätta main enbart till produktionsliknande miljöer, till exempel staging. Driftsättning till produktion ska ske med hjälp av Git-taggar med prefixet "release-", till exempel release-v1.0.0. För driftsättning till staging ska prefixet vara rc- (release candidate).
GPT-svar
Absolut, din metod för Continuous Deployment med specifika Git-taggkonventioner för staging- och produktionsmiljöer är en bra strategi. Så här kan du strukturera det här arbetsflödet:
Main-branchen som staging-miljö:
Main-branchen fungerar som en staging-liknande miljö. Varje merge till main utlöser en automatisk driftsättning till staging-miljön.
Detta gör att du kan testa i en miljö som liknar produktion så mycket som möjligt.
Git-taggar för staging och produktion:
Staging-taggar: Använd prefixet rc- (release candidate) för driftsättningar till staging. Exempelvis anger rc-v1.0.0 en release candidate för version 1.0.0. När du pushar en tagg med det här prefixet utlöser den en driftsättning till staging-miljön.
Produktionstaggar: Använd prefixet release- för driftsättningar till produktion. Taggar som release-v1.0.0 används för att utlösa manuella driftsättningar till produktionsmiljön. Det ger dig kontroll över vad som driftsätts till produktion och när.
Steg i arbetsflödet:
Utveckling: Utvecklare arbetar i feature- eller bugfix-brancher som utgår från main.
Kodgranskning och merge: När arbetet är klart skapas en pull request för att merga ändringarna till main. Efter kodgranskning och godkända CI-kontroller mergas ändringarna.
Automatisk driftsättning till staging: En merge till main utlöser automatiskt driftsättning till staging-miljön. Detta sker för slutlig testning och validering.
Taggning för release candidates: När teamet är nöjt med ändringarna i staging skapas en rc-tagg för att formellt markera en release candidate.
Driftsättning till produktion: När release candidate har testats och godkänts grundligt skapas en release-tagg. Denna tagg används sedan för att manuellt utlösa driftsättningen till produktionsmiljön.
Continuous Integration och driftsättning:
Konfigurera CI/CD-pipelines för att hantera olika miljöer baserat på taggningskonventionen.
Säkerställ att CI-pipelinen innehåller alla nödvändiga tester och kvalitetskontroller.
Dokumentation:
Dokumentera processen tydligt, inklusive hur och när du taggar för driftsättningar till staging och produktion.
Den här lösningen säkerställer en tydlig separation mellan driftsättningar till staging och produktion och ger teamet kontroll över releaseprocessen. Genom att använda olika taggar för staging (rc-) och produktion (release-) kan du enkelt hantera och följa olika releases genom miljöerna.
Slutsats: automatisera driftsättningar till produktionsliknande miljöer
Nu är jag nöjd med mitt arbetsflöde. Du kan arbeta på liknande sätt för att skapa ett arbetsflöde som du är nöjd med och vill gå vidare med.
Om du helt tappar bort dig i chattsessionen med AI kan det vara bättre att börja om från början i en ny session för att undvika missvisande svar.
Den här gången lyckades jag få resultat redan i den första chattsessionen, men många gånger har det inte varit så enkelt. Härnäst går jag vidare med att faktiskt generera pipelinen som kod, med Atlassian Bitbucket Pipelines som underliggande teknik.
Generativ AI för DevOps-pipelines
I det här avsnittet ska vi se hur Chat GPT-4 kan skapa en beskrivningsfil för en Bitbucket-pipeline som implementerar ovanstående.
Prompt #4
Här fortsätter jag att skriva promptar i samma chattsession, så att LLM:en har relevant kontext i bakgrunden.
Nu vill jag att du ger mig bitbucket-pipelines.yaml utifrån det senaste arbetsflödet som du nyligen svarade med. Ge mig pipelinen för min backend-tjänst som är implementerad med Python Flask och som jag vill driftsätta till Google Kubernetes på GCP.
Här fick jag en implementering på hög nivå där de flesta detaljer hade flyttats till separata shellskriptfiler. Det var inte min avsikt, så jag visar inte svaret här. Efter ytterligare diskussionsrundor fick jag dock det jag letade efter.
Promptar från #5 till #8
Flera promptar är vanliga när du arbetar med generativ AI i komplexa ämnen. AI kan inte utläsa dina exakta behov från en enda prompt med begränsad detaljnivå. Dessutom är det viktigt att dela upp större uppgifter i mindre, hanterbara delar. Processen kräver också en god förståelse för DevOps för att du ska kunna styra samtalet på ett effektivt sätt. Du bör inte förvänta dig att enkelt få bra resultat.
#5 – Okej, det här är lite för övergripande. Jag vill att du inkluderar bygge av Docker-images och push av images till Google Cloud Repository gcr.io. Inkludera även kommandon för gcloud CLI och kubectl. Lägg också till platshållare för miljövariabler och secrets där det behövs.
#6 – Det är bra, men hur fungerar det om taggen release-* utlöses manuellt?
#7 – Jag vill börja använda Bitbucket deployment environments. Kan du ge mig den senaste bitbucket-pipelines.yaml-filen med ändringar som inkluderar den informationen?
#8 – Jag vill ändra pipelinen så att Docker-imagen bara byggs en gång och sedan kan taggas om. Den ska inte behöva byggas om från början.
GPT-4-svar
För att ändra din pipeline så att Docker-imagen bara byggs en gång och sedan taggas om för olika miljöer behöver du göra några justeringar i din bitbucket-pipelines.yml. Tanken är att bygga Docker-imagen en gång, pusha den till Google Container Registry (GCR) med en generell tagg och sedan tagga om den för driftsättning till staging eller produktion vid behov.
Här är en uppdaterad version av din bitbucket-pipelines.yml-fil med dessa ändringar:
image: atlassian/default-image:2
pipelines:
default:
- step:
name: Build and Test
caches:
- pip
script:
- pip install -r requirements.txt
- python -m unittest discover tests
branches:
main:
- step:
name: Build and Push Docker Image
script:
- echo $GCLOUD_SERVICE_KEY | base64 --decode --ignore-garbage > ${HOME}/gcloud-service-key.json
- docker build -t gcr.io/$GCLOUD_PROJECT/your-app:latest .
- gcloud auth configure-docker --quiet
- docker push gcr.io/$GCLOUD_PROJECT/your-app:latest
- step:
name: Deploy to Staging
deployment: staging
script:
- echo "Deploying to Staging Environment"
- ./deploy-staging.sh # This script should handle the retagging for staging
tags:
'rc-*':
- step:
name: Retag and Deploy to Staging
deployment: staging
script:
- echo "Retagging and Deploying Release Candidate to Staging"
- ./retag-deploy-staging.sh # Script to retag the image for staging
'release-*':
- step:
name: Retag and Deploy to Production
deployment: production
trigger: manual
script:
- echo "Retagging and Deploying to Production Environment"
- ./retag-deploy-production.sh # Script to retag the image for production
definitions:
caches:
pip: ~/.cache/pip
Viktiga ändringar
Bygg en image en gång: Docker-imagen byggs och pushas bara en gång vid commits till main-branchen. Den taggas som latest.
Omtaggning för staging och produktion:
Skriptet ./deploy-staging.sh används för att driftsätta den senaste taggen direkt till staging-miljön.
För taggarna rc-* och release-* används separata skript (./retag-deploy-staging.sh och ./retag-deploy-production.sh). Skripten ska hantera att tagga om Docker-imagen med rätt tagg (baserat på commit- eller release-taggen) och sedan driftsätta den till respektive miljö.
Skript för retaggning och driftsättning
./deploy-staging.sh ska driftsätta den senaste imagen till staging utan retaggning.
./retag-deploy-staging.sh och ./retag-deploy-production.sh ska:Göra en pull av den senaste imagen från GCR.Retagga den med den specifika commit- eller release-taggen.Pusha tillbaka den retaggade imagen till GCR.Uppdatera Kubernetes-deploymenten så att den använder den nya taggen.
Gör en pull av den senaste imagen från GCR.
Retagga den med den specifika commit- eller release-taggen.
Pusha tillbaka den retaggade imagen till GCR.
Uppdatera Kubernetes-deploymenten så att den använder den nya taggen.
Det här tillvägagångssättet säkerställer att Docker-imagen bara byggs en gång, vilket sparar tid och resurser. Retaggningsskripten ger flexibilitet att hantera olika miljöer utan att behöva bygga om imagen. Kom ihåg att säkerställa att ditt GCP-tjänstkonto har nödvändiga behörigheter och att ersätta platshållarna med dina faktiska projektuppgifter.
Slutsats för LLM:s slutliga resultat
Upprepa de här stegen för varje komponent i ditt system, oavsett om det är en tjänst, ett UI eller en applikation. Utifrån min erfarenhet av Bitbucket pipelines kan jag bedöma svaren med ganska stor säkerhet och förstå vad som krävs för att göra detta operativt. Om jag däremot inte var bekant med teknikerna skulle jag förvänta mig att stöta på en del oväntade utmaningar.
När LLM:er blir mer avancerade och mer specialiserade versioner utvecklas kommer kvaliteten på svaren utan tvekan att förbättras. AI kommer att kraftigt snabba upp införandet av nya tekniker och processer inom DevOps.
Att uppnå en DevOps-basnivå i praktiken med AI
Där har du min demonstration av hur en DevOps-basnivå kan uppnås i praktiken med hjälp av AI. Det krävs inga avancerade kunskaper för att börja skriva prompts, men precis som i alla sporter får du bättre resultat med övning.
Det finns fortfarande flera saker att förbättra utifrån basnivån, till exempel omfattande Continuous Integration, inklusive bland annat DevSecOps och IaC.
Med hjälp av AI blir det enklare att komma i gång med DevOps-områden. Det finns mycket bra material tillgängligt på internet, och det verkar vara väl integrerat i LLM:er. Det är dock viktigt att förstå att designdiskussioner av den här typen är mer effektiva med de mest avancerade LLM:erna. Samma diskussion med exempelvis GPT-3.5 skulle vara väldigt annorlunda.
Ofta anses CI/CD vara en alltför stor investering för mindre projekt. Men nyttan överväger lätt kostnaderna som uppstår om det försummas eller implementeras i ett senare skede. Det bör inte längre finnas någon anledning att tveka inför att investera i DevOps från början.
Med tiden förväntar jag mig att allt mer omfattande utvecklingsplattformar växer fram, där många processer automatiseras och gör utveckling och DevOps mer abstrakta. Problemlösningsförmåga och en djup förståelse för de underliggande principerna kommer ändå att förbli viktiga.
Jag hoppas att det här blogginlägget har inspirerat dig att implementera DevOps från början och/eller förbättra din nuvarande situation.
Om du gillade det här blogginlägget kanske du också uppskattar vårt podcastavsnitt om AI i DevOps-toolchainen.
- Mjukvaruutveckling
- DevOps
- CI/CD
Subscribe to our newsletter
Related blogs