CI/CD for AI-modeller med Azure DevOps: kodeeksempler og forklaringer

22.06.2025

Å sette AI-modeller i produksjon uten automatisering er som å kjøre Formel 1 uten pit-stop-team: rå kraft, men total kaos. I denne guiden får du en gjennomgåelse av en presis, Azure-integrert CI/CD-pipeline for AI-modeller – komplett med YAML-kode og kommentarer som gjør det tydelig hva hvert steg gjør.

1. Hvorfor CI/CD er helt nødvendig for AI-prosjekter

AI-leveranser skiller seg fra tradisjonelle apper ved at:

  1. Datakilder drifter over tid, noe som kan knekke modellen i produksjon.

  2. Eksperimenter med hyperparametere og rammeverk raskt snur kodebasen.

  3. Modell-versjoner sprer seg i uoversiktlige filnavn.

  4. Infrastruktur omfatter GPU- og CPU-jobber, Docker-images og Kubernetes-deploys.

  5. Testing krever målinger av nøyaktighet, latency, ressursbruk og data-drift.

Ved å ta i bruk CI/CD (eller MLOps), sikrer du at alle commits valideres automatisk, at modeller versjoneres på en entydig måte, og at produksjonssetting skjer uten manuell risiko.

2. Azure DevOps i korte trekk

I Azure DevOps bruker vi hovedsakelig:

  • Azure Pipelines for multistage, YAML-definerte CI/CD-flyter

  • Agent-puljer (Microsoft-hosted og self-hosted GPU/CPU)

  • Environments med godkjenninger og audit-trail

  • Artefakter for modellfiler, Docker-images og rapporter

  • Integrerte tasks for Docker, Kubernetes, Azure CLI, Azure ML, DVC/MLflow

Dette gir full kontroll over alt fra bygg og test til deploy og overvåkning.

3. Multistage YAML-pipeline med forklarende kommentarer

*Filen .azure-pipelines/ci-cd.yaml kan se slik ut:

trigger:

    branches:

        include:

            - main                                                                     # Pipeline kjører på hvert push til main

variables:

   TRAIN_DATA: '$(Pipeline.Workspace)/data/train.csv'

   MODEL_OUT: '$(Pipeline.ArtifactStagingDirectory)/model.pkl'

stages:

    - stage: Build_and_Test

       displayName: '1. Kodekvalitet og enhetstester'

       jobs:

          - job: Lint_and_UnitTests

             displayName: 'Lint + pytest'

             pool:

                vmImage: 'ubuntu-latest'

            steps:

             - checkout: self                                                                                        # Hent repo-innhold

             - task: UsePythonVersion@0                                                        # Velg Python-versjon

                 inputs:

                    versionSpec: '3.10'

            - script: |

                  pip install -r requirements.txt

                 flake8 src tests # Sjekk kode­stil

                 pytest --maxfail=1 --disable-warnings -q

              displayName: 'Installer + test'

    - stage: Sanity_Train

      displayName: '2. Sanity-trening'

     dependsOn: Build_and_Test

     jobs:

        - job: Quick_Train

           displayName: 'Rask modelltrening'

           pool:

                vmImage: 'ubuntu-latest'

          steps:

             - checkout: self

             - script: |

                    pip install -r requirements.txt

                    python train.py \

                       --data $(TRAIN_DATA) \

                       --epochs 1 \

                       --output $(MODEL_OUT)

               displayName: 'Mini-train'

             - publish: $(MODEL_OUT)                                       # Publiser modellfil som artefakt

                artifact: 'ci-model'


  • trigger: definerer når pipelinen kjører
  • stages: bryter opp prosessen i logiske trinn
  • publish: gjør modellutdata tilgjengelig for neste stage


4. Data- og modellversjonering med DVC

Store datasett bør håndteres utenfor Git. Bruk *DVC mot Azure Blob:

- stage: Data_Versioning

   displayName: '3. Data-versjonering'

   dependsOn: Sanity_Train

   jobs:

      - job: DVC_Pull

         displayName: 'Hent data med DVC'

         pool:

              vmImage: 'ubuntu-latest'

         steps:

            - checkout: self

            - script: |

                   pip install dvc[azure]

                  dvc pull data/train.dvc                                                                      # Synk data til agent

               displayName: 'DVC pull'

Med dette steget får hver agent nøyaktig samme versjon av treningsdata.

5. Deploy til staging og produksjon

Når CI er godkjent, kan vi *deploye til staging:

  - stage: Deploy_Staging

      displayName: '4. Deploy til staging'

      dependsOn: Data_Versioning

      jobs:

          - deployment: AKS_Staging

              displayName: 'AKS: staging'

              environment: 'staging'                                                              # Gir godkjenninger i GUI

      pool:

           vmImage: 'ubuntu-latest'

      strategy:

          runOnce:

              preDeploy:

                  steps:

                       - download: current

                           artifact: 'ci-model'                                                               # Hent modellartefakt

              deploy:

                   steps:

                      - task: Docker@2                                                        # Bygg og push Docker-image

                          inputs:

                              containerRegistry: 'MinACR-Connection'

                              repository: 'ml-service'

                              command: 'buildAndPush'

                              tags: '$(Build.BuildId)'

                      - task: Kubernetes@1                                                                            # Deploy til AKS

                         inputs:

                              connectionType: 'Azure Resource Manager'

                              azureSubscription: 'MinAzureSub'

                              azureResourceGroup: 'RG-AKS'

                              kubernetesCluster: 'my-aks'

                              namespace: 'staging'

                              command: 'apply'

                              useConfigurationFile: true

                              configuration: 'k8s/deploy-staging.yaml'

  • environment: aktiverer godkjenninger og audit-trail
  • runOnce: sikrer automatisk rollback hvis preDeploy eller deploy feiler

For produksjonssett bruker du tilsvarende stage med environment: 'production' og eventuelle strengere godkjenninger. 

6. AI-spesifikke tester

I tillegg til enhetstester *legger vi inn:

- stage: Model_Validation

    displayName: '5. Modellvalidering'

    dependsOn: Deploy_Staging

    jobs:

       - job: Regression_Test

           displayName: 'Regresjonstest'

           pool:

                vmImage: 'ubuntu-latest'

            steps:

                - download: current

                    artifact: 'ci-model'                                                                                  # Hent modellfil

                - script: |

                        pip install -r requirements.txt

                        python validate_model.py \

                             --model outputs/model.pkl \

                             --min_accuracy 0.75                                                 # Feiler hvis under terskel

                    displayName: 'Kjør regresjonstest'

  • validate_model.py bør måle F1/AUC mot en test-dataset
  • Du kan også legge inn latency- og ressurs-tester i samme eller egne jobber

7. Skalerbarhet med agent-puljer

For CPU-jobber bruker du Microsoft-hosted agenter. For trening på GPU setter du opp egne *VMer:

pool:

    name: 'GPU-Pool'                                                            # Navnet på self-hosted agent-pool

    demands:

          - cuda                                                                       # Krever at agenten har CUDA installert

Administrer agent-pooler under Project settings → Agent pools. Bruk Azure VM Scale Sets for autoskalering 

8. Zero-downtime og rollback

Rull ut med *rolling-strategi for å unngå avbrudd:

strategy:

   rolling:

       maxSurge: 1                                                                                                    # Tillat en ekstra pod

       maxUnavailable: 0                                 # Ingen gamle pods skal tas ned før nye er klare

  • Gir sømløs oppdatering
  • Automatiserer rollback ved feil

9. Integrasjon med Azure Machine Learning

For å registrere modellen i *Azure ML Workspace:

- stage: Register_Model

    displayName: '6. Registrer modell i Azure ML'

    dependsOn: Model_Validation

    jobs:

     - job: RegisterML

         displayName: 'Azure CLI: Modellregistrering'

         pool:

              vmImage: 'ubuntu-latest'

         steps:

             - download: current

                 artifact: 'ci-model'

             - task: AzureCLI@2

                 inputs:

                     azureSubscription: 'MinAzureSub'

                     scriptType: bash

                     scriptLocation: inlineScript

                     inlineScript: |

                         # Logg inn via service connection

                         az ml model register \

                           --name kredittscorer \

                           --version 1 \

                           --resource-group RG-ML \

                           --workspace-name ml-ws \

                           --path outputs/model.pkl

               displayName: 'Registrer modell'

Denne jobben sørger for at hver godkjent modellversjon havner i Azure ML. 

10. Overvåkning og varsling

Sikre at du får varsler ved:

  • Pipeline-feil: Konfigurer notifikasjoner til Teams eller e-post under Project settings → Notifications

  • API-metrikker: Bruk Application Insights på Kubernetes-servicen for latency, throughput og feilrate

  • Data-drift: Sett opp en Log Analytics-query som måler Population Stability Index og sender alert ved store avvik

Lag gjerne et dashboard i Azure DevOps for å følge pipelinens status, kø-lengde og gjennomføringstid.

11. Oppsummering av beste praksis

  1. Versjoner alt: Git for kode, DVC/MLflow for data, Terraform/ARM for infrastruktur.

  2. Korte CI-treninger: Minimer trenings-tid i CI, kjør full trening i egne jobber.

  3. Segreger miljøer: Dev, staging og prod med egne godkjenninger.

  4. Bred testdekning: Enhet, integrasjon, regresjon, latency og data-drift.

  5. Automatisert rollback: Bruk runOnce eller rolling i deployment.

  6. Skalér med egne agenter: GPU-pooler og autoscaling for tunge jobber.

  7. Helhetlig overvåkning: Pipeline-varsler + App Insights + Log Analytics.

12. Case: Kredittscoremodell i bank

  1. Feature-branch: Data scientist pusher feature/credit-score.

  2. CI kjører: Lint → pytest → DVC pull → mini-train → artefakt.

  3. Staging-CD: Docker build/push → AKS deploy → integrasjonstest → manuell godkjenning.

  4. Prod-CD: Trafikksplitting 10/90 → full utrulling.

  5. Overvåkning: App Insights varsler ved PSI > 0,1.

  6. Retraining: Daglig pipeline kjører trening med ny data.

På denne måten kan banken oppdatere modell med full kontroll flere ganger per uke.

13. Veien videre

Utforsk avanserte temaer:

  • GitOps for ML – deklarer pipelines og infrastruktur som kode

  • Serverless inferens med Azure Functions for sporadiske spørringer

  • Feature Stores (Feast, Tecton) integrert i trenings- og deploy-pipelines

  • Explainable AI-verifisering i CI-steg for å sikre forklaringsstabilitet

  • Data-drift-triggered retraining med automatiske oppdateringer

Start med denne malen, tilpass etter egne behov, og opplev hvor raskt dere kan flytte AI-modeller fra idé til pålitelig produksjon. Lykke til! 


*Forbehold om kode

Koden i denne guiden er levert som eksempler og utgangspunkt. Den er ikke testet mot alle tenkelige konfigurasjoner eller miljøer. Sørg derfor for å:

  • Validere og tilpasse alle YAML-filer og skript mot din egen Azure DevOps-instans, agent-pool, resource group, ACR, AKS-kluster og Azure ML-arbeidsområde

  • Kjøre fullstendige tester – enhet, integrasjon, ytelse og sikkerhet – i egne staging- eller test-miljøer før produksjonssetting

  • Gjennomføre grundig gjennomgang av service connections, rollebasert tilgang og godkjenningsregler i dine miljøer

Forfatteren påtar seg intet ansvar for uforutsette feil, tap av data, driftsavbrudd eller andre konsekvenser som måtte oppstå ved bruk av eksempelkoden. Leseren bruker den på egen risiko.