Kas yra GitLab CI/CD ir kodėl tai svarbu
Jei dar nesinaudojate automatizuotais diegimo procesais, tikriausiai praleidžiate daug laiko rankiniam kodui į serverius kelti, testams vykdyti ir kitiems rutininiams dalykams. GitLab CI/CD – tai įrankis, kuris leidžia automatizuoti visą kelią nuo kodo pakeitimo iki jo patekimo į produkciją. Ir tai nėra kažkokia raketų mokslo dalis – pradėti galima iš paprastų dalykų ir palaipsniui tobulinti.
GitLab CI/CD veikia pagal pipeline principą – tai tarsi konvejeris, kuriame jūsų kodas eina per įvairius etapus: kompiliavimą, testavimą, saugumo patikrinimus ir galų gale diegimą. Kiekvienas etapas gali turėti vieną ar kelias užduotis (jobs), kurios vykdomos tam tikromis sąlygomis.
Didžiausias privalumas – tai, kad viskas aprašoma kodu. Jūsų projekto šakniniame kataloge sukuriate .gitlab-ci.yml failą, ir GitLab automatiškai pradeda jį naudoti. Jokių sudėtingų sąsajų ar papildomų įrankių diegti nereikia.
Pirmieji žingsniai su .gitlab-ci.yml failu
Pradėkime nuo paprasčiausio pavyzdžio. Sukurkite projekto šakniniame kataloge failą .gitlab-ci.yml ir įrašykite:
stages:
- test
- build
test_job:
stage: test
script:
- echo "Vykdomi testai"
- npm test
build_job:
stage: build
script:
- echo "Kuriamas build"
- npm run build
Šis pavyzdys apibrėžia du etapus (stages) ir po vieną užduotį kiekvienam. Etapai vykdomi nuosekliai – pirmiausia test, tada build. Jei test etapas nepavyksta, build net neprasidės.
Svarbu suprasti, kad kiekviena užduotis vykdoma atskirame Docker konteineryje (arba kitokioje izoliuotoje aplinkoje, priklausomai nuo jūsų runner konfigūracijos). Tai reiškia, kad tarp užduočių failai neišlieka, nebent naudojate artifacts ar cache mechanizmus.
Kai tik įkelsite šį failą į GitLab repozitoriją, sistema automatiškai aptiks pakeitimą ir paleisis pipeline. Galite stebėti eigą per GitLab sąsają – CI/CD > Pipelines skiltyje.
Runner’ių supratimas ir konfigūravimas
Pipeline’ai nevyksta GitLab serveryje – jiems reikia runner’ių. Tai programos, kurios klauso GitLab nurodymų ir vykdo užduotis. GitLab.com naudotojams suteikiami bendri (shared) runner’iai, bet jei naudojate savo GitLab instaliaciją arba norite daugiau kontrolės, turėsite sukonfigūruoti savo.
Runner’io įdiegimas Linux sistemoje gana paprastas:
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash sudo apt-get install gitlab-runner
Po įdiegimo reikia jį užregistruoti:
sudo gitlab-runner register
Registracijos metu prašys GitLab URL, registracijos token (rasite projekto Settings > CI/CD > Runners), aprašymo ir executor tipo. Dažniausiai naudojamas Docker executor – jis leidžia kiekvieną užduotį vykdyti atskirame konteineryje, kas užtikrina švarią aplinką.
Praktinis patarimas: jei planuojate dažnai vykdyti pipeline’us, verta sukonfigūruoti cache ir artifacts saugojimą. Tai gerokai pagreitins procesus, nes nereikės kaskart iš naujo parsisiųsti visų priklausomybių.
Sudėtingesnė konfigūracija su kintamaisiais ir sąlygomis
Realūs projektai retai būna tokie paprasti. Dažniausiai reikia skirtingų veiksmų skirtingoms šakoms, aplinkos kintamųjų, slaptažodžių ir kitų niuansų. Štai išplėstas pavyzdys:
variables:
NODE_ENV: "production"
DOCKER_DRIVER: overlay2
stages:
- test
- build
- deploy
test_job:
stage: test
image: node:16
before_script:
- npm ci
script:
- npm run lint
- npm test
coverage: '/Lines\s*:\s*(\d+\.\d+)%/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
build_job:
stage: build
image: node:16
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
only:
- main
- develop
deploy_production:
stage: deploy
script:
- echo "Diegiama į produkciją"
- ./deploy.sh production
environment:
name: production
url: https://example.com
only:
- main
when: manual
Čia matome kelis svarbius dalykus. Pirma, variables sekcija leidžia apibrėžti kintamuosius, kurie bus prieinami visose užduotyse. Antra, image direktyva nurodo, kokį Docker image’ą naudoti. Trečia, artifacts leidžia išsaugoti failus tarp užduočių ar net parsisiųsti juos vėliau.
Ypač naudinga yra only direktyva – ji leidžia kontroliuoti, kada užduotis vykdoma. Šiame pavyzdyje deploy į produkciją vyksta tik iš main šakos ir tik rankiniu būdu (when: manual).
Slaptažodžių ir jautrių duomenų valdymas
Niekada nerašykite slaptažodžių ar API raktų tiesiai į .gitlab-ci.yml failą. GitLab turi puikų mechanizmą jautriems duomenims saugoti – CI/CD kintamuosius.
Eikite į Settings > CI/CD > Variables ir pridėkite reikiamus kintamuosius. Galite juos padaryti protected (prieinami tik protected šakoms) arba masked (nerodomi logų išvestyje). Pavyzdžiui, jei reikia AWS kredencialų:
deploy_to_aws:
stage: deploy
script:
- aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
- aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
- aws s3 sync dist/ s3://my-bucket/
Kintamieji $AWS_ACCESS_KEY_ID ir $AWS_SECRET_ACCESS_KEY bus automatiškai įtraukti iš projekto nustatymų. Jei juos pažymėjote kaip masked, logų išvestyje vietoj jų reikšmių matysite [masked].
Dar vienas svarbus dalykas – file tipo kintamieji. Jei reikia perduoti visą failą (pvz., SSH raktą ar konfigūraciją), galite sukurti file tipo kintamąjį, ir GitLab sukurs laikinąjį failą su tuo turiniu:
deploy_via_ssh:
script:
- chmod 600 $SSH_PRIVATE_KEY
- ssh -i $SSH_PRIVATE_KEY user@server "cd /var/www && git pull"
Cache ir artifacts – greičio optimizavimas
Vienas didžiausių naujokų klaidų – ignoruoti cache ir artifacts galimybes. Skirtumas tarp jų paprastas: cache naudojamas priklausomybėms, kurios keičiasi retai (pvz., node_modules), o artifacts – failams, kuriuos norite perduoti tarp užduočių ar išsaugoti po pipeline’o pabaigos.
Štai kaip efektyviai naudoti cache:
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
test_job:
stage: test
before_script:
- npm ci --cache .npm --prefer-offline
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
- .npm/
script:
- npm test
Naudojant package-lock.json kaip cache raktą, cache bus atnaujintas tik kai pasikeičia priklausomybės. Tai gerokai pagreitina pipeline’us – vietoj 2-3 minučių npm install gali užtrukti tik 10-20 sekundžių.
Artifacts naudojimas build rezultatams:
build_job:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/
expire_in: 30 days
deploy_job:
stage: deploy
dependencies:
- build_job
script:
- rsync -av dist/ user@server:/var/www/
dependencies direktyva nurodo, iš kurių užduočių artifacts reikia parsisiųsti. Jei jos nenurodysite, bus parsisiųsti visi ankstesnių etapų artifacts, kas gali nereikalingai lėtinti procesą.
Docker image’ų kūrimas ir naudojimas
Jei jūsų projektas naudoja Docker, GitLab CI/CD puikiai integruojasi su konteinerių registrais. Galite kurti image’us ir automatiškai juos kelti į GitLab Container Registry arba Docker Hub.
Pirmiausia įsitikinkite, kad turite Dockerfile projekte. Tada galite naudoti tokią konfigūraciją:
build_docker:
stage: build
image: docker:latest
services:
- docker:dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
- |
if [ "$CI_COMMIT_BRANCH" == "main" ]; then
docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG $CI_REGISTRY_IMAGE:latest
docker push $CI_REGISTRY_IMAGE:latest
fi
docker:dind (Docker-in-Docker) service leidžia vykdyti Docker komandas pipeline’o viduje. GitLab automatiškai suteikia kintamuosius kaip $CI_REGISTRY, $CI_REGISTRY_USER ir pan., todėl autentifikacija veikia be papildomo konfigūravimo.
Praktinis patarimas: naudokite multi-stage builds Dockerfile’uose. Tai leidžia sumažinti galutinio image’o dydį ir pagreitinti deployment:
# Dockerfile pavyzdys FROM node:16 AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build FROM nginx:alpine COPY --from=builder /app/dist /usr/share/nginx/html
Įprastos problemos ir jų sprendimai
Konfigūruojant GitLab CI/CD, neišvengiamai susiduriate su iššūkiais. Štai keletas dažniausių problemų ir kaip jas spręsti.
Pipeline’as nepasileižia po commit’o
Patikrinkite, ar .gitlab-ci.yml failas yra projekto šakniniame kataloge ir ar jame nėra sintaksės klaidų. GitLab turi įtaisytą validatorių – eikite į CI/CD > Editor ir įklijuokite savo konfigūraciją. Jis parodys klaidas, jei tokių yra.
Runner’is neprieinamas arba užimtas
Jei naudojate savo runner’ius, įsitikinkite, kad jie veikia: sudo gitlab-runner status. Taip pat patikrinkite, ar runner’is turi tinkamus tag’us. Jei jūsų užduotyje nurodėte tags: [docker], bet runner’is neturi šio tag’o, užduotis liks eilėje.
Cache neveikia arba per lėtai
Įsitikinkite, kad cache keliai tikrai egzistuoja ir yra teisingi. Taip pat svarbu naudoti tinkamą cache raktą – jei raktas keičiasi kiekviename pipeline’e, cache bus visada naujas. Naudokite key: files: su failais, kurie keičiasi retai.
Artifacts per dideli arba greitai išnyksta
Galite kontroliuoti artifacts galiojimo laiką su expire_in. Jei artifacts labai dideli, apsvarstykite, ar tikrai reikia visų failų. Kartais geriau naudoti external storage ir artifacts’uose saugoti tik nuorodas.
Slaptažodžiai matomi loguose
Niekada nenaudokite echo ar panašių komandų su slaptažodžiais. Jei vis tiek reikia debug’inti, naudokite GitLab masked variables. Taip pat galite išjungti logų rodymo dalį su echo "::add-mask::$SECRET_VALUE" tipo konstrukcijomis, nors GitLab šiuo metu šio funkcionalumo neturi natūraliai – geriau tiesiog naudoti masked variables.
Kai viskas veikia – ką toliau?
Kai jau turite veikiantį pipeline’ą, laikas pagalvoti apie tobulinimus. Galite pridėti saugumo skenavimą su įrankiais kaip Trivy ar SAST (Static Application Security Testing), kurį GitLab siūlo kaip template’ą.
Integruokite code quality patikrinimus:
include:
- template: Code-Quality.gitlab-ci.yml
code_quality:
artifacts:
reports:
codequality: gl-code-quality-report.json
Naudokite dynamic environments preview funkcionalumą – kiekvienam merge request’ui galite automatiškai sukurti atskirą aplinką:
deploy_review:
stage: deploy
script:
- echo "Diegiama review aplinka"
- ./deploy-review.sh $CI_COMMIT_REF_SLUG
environment:
name: review/$CI_COMMIT_REF_SLUG
url: https://$CI_COMMIT_REF_SLUG.review.example.com
on_stop: stop_review
only:
- merge_requests
stop_review:
stage: deploy
script:
- ./cleanup-review.sh $CI_COMMIT_REF_SLUG
environment:
name: review/$CI_COMMIT_REF_SLUG
action: stop
when: manual
Tai leidžia testuotojams ar klientams peržiūrėti pakeitimus prieš juos suliejant į pagrindinę šaką. Kiekvienas merge request gauna savo URL, o po merge’o aplinka gali būti automatiškai išvalyta.
Nepamiršite monitoringo ir pranešimų. GitLab gali siųsti pranešimus į Slack, Microsoft Teams ar kitus įrankius, kai pipeline’ai nepavyksta. Tai konfigūruojama per Settings > Integrations.
Galiausiai, dokumentuokite savo pipeline’us. Nors YAML failai yra gana skaitomi, sudėtingesnėms konfigūracijoms verta turėti README su paaiškinimais, kodėl tam tikri sprendimai buvo priimti. Tai labai padeda naujiems komandos nariams ar jums patiems po kelių mėnesių, kai pamirštate detales.
GitLab CI/CD – tai galingas įrankis, bet jo tikroji vertė atsiskleidžia tik tada, kai jį pritaikote savo projekto poreikiams. Pradėkite paprastai, eksperimentuokite, mokykitės iš klaidų ir palaipsniui kurkite vis sudėtingesnius automatizavimo procesus. Kai pipeline’ai veikia sklandžiai, jūsų komanda gali sutelkti dėmesį į tai, kas iš tiesų svarbu – kurti kokybišką kodą.
