Skaffold: „Kubernetes“ kūrimas

Kas tas Skaffold ir kodėl jis turėtų jus dominti

Jei kada nors bandėte kurti aplikacijas Kubernetes aplinkai, tikriausiai žinote, koks tai gali būti skausmingas procesas. Keisti kodą, sukurti Docker image’ą, push’inti į registry, atnaujinti Kubernetes manifest’us, deploy’inti – ir tai tik tam, kad pamatytumėte, ar jūsų pakeitimas veikia. O jei neveikia? Kartokite viską iš naujo. Štai čia ir ateina į pagalbą Skaffold.

Skaffold – tai Google sukurtas open-source įrankis, kuris automatizuoja visą šį ciklą. Jis stebi jūsų kodo pakeitimus, automatiškai build’ina image’us, deploy’ina į Kubernetes klasterį ir net sugeba stream’inti log’us tiesiai į jūsų terminalą. Skamba kaip sapnas, tiesa? Na, realybė yra šiek tiek sudėtingesnė, bet vis tiek daug geresnė nei rankinis darbas.

Pats Skaffold veikia kaip orkestravimo sluoksnis, kuris jungia jau egzistuojančius įrankius – Docker, kubectl, Helm, Kustomize ir kitus. Jis nėra bandymas pakeisti šiuos įrankius, o greičiau suteikti jiems bendrą sąsają ir automatizuoti rutininius procesus. Tai reiškia, kad jūs vis dar naudojate tuos pačius įrankius, kuriuos pažįstate, tik dabar jie dirba kartu daug sklandžiau.

Kaip pradėti dirbti su Skaffold

Pradėti su Skaffold yra gana paprasta. Pirma, jums reikės įdiegti patį įrankį. Jei naudojate macOS, pakanka paleisti brew install skaffold. Linux’e galite atsisiųsti binary tiesiog iš GitHub releases puslapio. Windows naudotojams taip pat yra galimybių, nors dažniausiai rekomenduojama naudoti WSL2.

Kai turite įdiegtą Skaffold, jums reikės sukurti konfigūracijos failą skaffold.yaml savo projekto root’e. Štai paprasčiausias pavyzdys:


apiVersion: skaffold/v4beta6
kind: Config
build:
artifacts:
- image: my-app
docker:
dockerfile: Dockerfile
deploy:
kubectl:
manifests:
- k8s/*.yaml

Šis failas sako Skaffold’ui tris dalykus: kokią API versiją naudojame, kaip build’inti mūsų aplikaciją (šiuo atveju naudojant Dockerfile) ir kaip ją deploy’inti (naudojant kubectl su manifest’ais iš k8s direktorijos). Paprasta, ar ne?

Dabar galite paleisti skaffold dev ir stebėti magiją. Skaffold pradės stebėti jūsų failus, build’ins image’ą, deploy’ins į jūsų Kubernetes klasterį (gali būti ir lokalus minikube ar kind) ir pradės rodyti log’us. Kai pakeičiate kodą ir išsaugote failą, viskas automatiškai atsinaujina.

Development workflow’ai ir jų optimizavimas

Vienas iš didžiausių Skaffold privalumų yra tai, kad jis palaiko kelis skirtingus development workflow’us. Galite naudoti skaffold dev kasdieniniam darbui – tai continuous development režimas, kuris stebi pakeitimus ir automatiškai rebuild’ina bei redeploy’ina. Bet yra ir daugiau galimybių.

skaffold debug režimas leidžia prijungti debugger’į prie jūsų aplikacijos, veikiančios Kubernetes’e. Tai veikia su įvairiomis kalbomis – Node.js, Python, Java, Go. Skaffold automatiškai konfigūruoja reikiamus port forward’us ir environment variables, kad galėtumėte naudoti savo įprastą IDE debugger’į.

Jei norite tiesiog greitai išbandyti kažką, skaffold run padarys vienkartinį build ir deploy. O kai esate pasirengę deploy’inti į production, skaffold render sugeneruos galutines Kubernetes manifest’us su teisingais image tag’ais, kuriuos galite commit’inti į git arba perduoti savo CI/CD pipeline’ui.

Vienas iš geriausių Skaffold feature’ų yra file sync. Vietoj to, kad rebuild’intų visą Docker image’ą kiekvieną kartą, kai pakeičiate failą, Skaffold gali tiesiog nukopijuoti pakeistą failą į veikiantį pod’ą. Tai veikia puikiai su interpretavimo kalbomis kaip Python ar Node.js, kur galite naudoti hot reload. Konfigūracija atrodo taip:


build:
artifacts:
- image: my-node-app
sync:
manual:
- src: 'src/**/*.js'
dest: /app/src

Integracijos su kitais įrankiais

Skaffold nėra izoliuota sala – jis puikiai integruojasi su visa Kubernetes ekosistema. Jei naudojate Helm chart’us savo aplikacijoms valdyti, Skaffold tai palaiko iš dėžės. Tiesiog nurodykite chart’o kelią konfigūracijoje:


deploy:
helm:
releases:
- name: my-app
chartPath: helm/my-app
valuesFiles:
- helm/values-dev.yaml

Kustomize naudotojai taip pat nelieka nuskriausti. Galite naudoti Kustomize overlay’us skirtingoms aplinkoms ir Skaffold automatiškai pritaikys reikiamus pakeitimus. Tai ypač patogu, kai turite dev, staging ir production aplinkas su skirtingomis konfigūracijomis.

Jei jūsų build procesas yra sudėtingesnis ir naudojate Bazel, BuildKit ar net custom build script’us, Skaffold ir tai gali. Jis palaiko įvairius build’erius ir leidžia net sukurti custom builder’į, jei jums reikia kažko specifinio.

CI/CD integracijos taip pat yra svarbios. Skaffold puikiai veikia su Jenkins, GitLab CI, GitHub Actions, CircleCI ir kitais. Dažniausiai CI pipeline’e naudojate skaffold build image’ų build’inimui ir tag’inimui, o paskui skaffold deploy arba skaffold render deployment’ui. Tai leidžia išlaikyti tą patį workflow’ą tiek lokalioje development aplinkoje, tiek CI/CD.

Profiles ir multi-environment konfigūracijos

Realybėje retai kada dirbate tik su viena aplinka. Turite lokalią development aplinką, galbūt shared dev klasterį, staging, production. Kiekvienai reikia šiek tiek skirtingos konfigūracijos. Čia praverčia Skaffold profiles.

Profile’ai leidžia apibrėžti konfigūracijos variantus tame pačiame skaffold.yaml faile. Pavyzdžiui:


profiles:
- name: production
build:
artifacts:
- image: my-app
docker:
dockerfile: Dockerfile.prod
deploy:
helm:
releases:
- name: my-app
chartPath: helm/my-app
valuesFiles:
- helm/values-prod.yaml

Tada galite paleisti skaffold dev -p production ir Skaffold naudos production profile’į. Tai leidžia išlaikyti visas konfigūracijas vienoje vietoje, bet turėti lankstumo skirtingoms aplinkoms.

Profile’ai gali override’inti bet kurią konfigūracijos dalį – build settings, deploy strategiją, image registry, resource limits. Galite turėti profile’į, kuris naudoja lokalų Docker daemon’ą development’ui, ir kitą, kuris build’ina cloud’e production’ui. Arba profile’į su debug įjungtu ir be jo.

Dar vienas naudingas dalykas – activation. Galite sukonfigūruoti, kad profile’as automatiškai aktyvuotųsi pagal tam tikras sąlygas, pavyzdžiui, Kubernetes context’ą. Jei jūsų kubectl context’as yra „production”, automatiškai naudojamas production profile’as. Tai sumažina klaidų tikimybę, kai per klaidą deploy’inate dev konfigūraciją į production.

Performance optimizavimas ir best practices

Nors Skaffold automatizuoja daug dalykų, vis tiek yra būdų, kaip padaryti jį dar greitesnį ir efektyvesnį. Pirmiausia – Docker layer caching. Įsitikinkite, kad jūsų Dockerfile’ai yra optimizuoti. Dažnai keičiamą kodą kopijuokite paskutiniuose layer’iuose, o dependencies ir kitus rečiau keičiamus dalykus – pradžioje.

Jei naudojate lokalų Kubernetes klasterį kaip minikube ar kind, įjunkite local image loading. Tai leidžia Skaffold’ui tiesiog load’inti image’us į klasterio Docker daemon’ą vietoj to, kad push’intų į registry ir paskui pull’intų atgal. Tai sutaupo daug laiko:


build:
local:
push: false

File sync, apie kurį minėjau anksčiau, yra kitas didelis performance booster’is. Bet būkite atsargūs – jis veikia tik su tam tikrais failų tipais. Binary’ai ar compiled code’as vis tiek reikalauja full rebuild’o. Tačiau frontend assets, configuration files, script’ai – visi šie puikiai tinka sync’ui.

Jei turite daug microservice’ų viename repo (monorepo), naudokite artifact dependencies. Tai leidžia Skaffold’ui suprasti, kurie service’ai priklauso vieni nuo kitų ir rebuild’inti tik tai, kas tikrai pasikeitė. Taip pat galite naudoti --skip-tests flag’ą development metu, jei testai užtrunka ilgai – tiesiog nepamirškite jų paleisti prieš commit’indami.

Dar vienas patarimas – naudokite .dockerignore failą. Jei jūsų Docker build context’e yra daug nereikalingų failų (node_modules, .git, build artifacts), build’as bus lėtesnis. Dockerignore padeda išvengti šios problemos.

Troubleshooting ir debugging

Kai kas nors neveikia (o taip nutinka), Skaffold turi keletą įrankių, kurie padeda suprasti, kas vyksta. Pirmiausia – verbose logging. Paleiskite su -v debug flag’u ir pamatysite daug daugiau informacijos apie tai, ką Skaffold daro:

skaffold dev -v debug

Tai parodys visas komandas, kurias Skaffold vykdo, Docker build output’ą, kubectl komandas – viską. Dažnai tai padeda greitai identifikuoti problemą.

Jei turite problemų su image build’u, galite paleisti skaffold build atskirai, be deploy’inimo. Tai leidžia izoliuoti build problemas nuo deployment problemų. Panašiai, skaffold deploy gali būti naudojamas deployment’ui su jau egzistuojančiais image’ais.

Viena dažna problema – image pull errors. Jei Kubernetes negali pull’inti jūsų image’o, patikrinkite: ar push’inote į teisingą registry? Ar Kubernetes turi credentials tam registry’ui? Ar image tag’as teisingas? Skaffold paprastai automatiškai tvarko tag’us, bet jei naudojate custom konfigūraciją, lengva suklysti.

Kita dažna problema – port conflicts. Jei Skaffold bando forward’inti portą, kuris jau užimtas, gausite klaidą. Galite arba uždaryti programą, kuri naudoja tą portą, arba pakeisti Skaffold konfigūraciją naudoti kitą portą. Port forwarding konfigūruojamas taip:


portForward:
- resourceType: deployment
resourceName: my-app
port: 8080
localPort: 9090

Realūs scenarijai ir kaip juos išspręsti su Skaffold

Pažiūrėkime į keletą realių situacijų, su kuriomis susiduria developeriai, ir kaip Skaffold padeda jas išspręsti. Pirmas scenarijus – turite microservice’ų architektūrą su 5-10 service’ų. Visi jie turi būti paleisti kartu, kad aplikacija veiktų. Be Skaffold, turėtumėte build’inti ir deploy’inti kiekvieną atskirai. Su Skaffold, tiesiog išvardijate visus artifact’us:


build:
artifacts:
- image: frontend
context: ./frontend
- image: api-gateway
context: ./api-gateway
- image: user-service
context: ./services/user
- image: order-service
context: ./services/order

Dabar skaffold dev stebi visus šiuos service’us ir atnaujina tik tuos, kurie pasikeitė. Jei keičiate tik frontend kodą, tik frontend bus rebuild’intas ir redeploy’intas. Kiti service’ai lieka nepaliesti.

Antras scenarijus – turite frontend aplikaciją, kuri development metu turėtų naudoti hot reload, bet production’e turėtų būti statically built. Čia profiles išgelbsti:


build:
artifacts:
- image: frontend
docker:
dockerfile: Dockerfile.dev
sync:
manual:
- src: 'src/**/*'
dest: /app/src

profiles:
- name: production
build:
artifacts:
- image: frontend
docker:
dockerfile: Dockerfile.prod

Trečias scenarijus – dirbate su komanda ir kiekvienas turi savo lokalią development aplinką, bet kartais reikia deploy’inti į shared dev klasterį. Galite naudoti environment variables Skaffold konfigūracijoje:


build:
artifacts:
- image: gcr.io/{{.PROJECT_ID}}/my-app

Tada kiekvienas developeris gali nustatyti savo PROJECT_ID ir Skaffold naudos tą vertę. Arba galite naudoti skirtingus profiles skirtingiems klasteriams.

Ką daryti, kai Skaffold tampa per daug

Būkime sąžiningi – ne kiekvienam projektui reikia Skaffold. Jei turite vieną paprastą aplikaciją, kuri retai keičiasi, galbūt paprastas bash script’as su docker build ir kubectl apply bus pakankamai geras. Skaffold prideda dar vieną abstraction layer’į, o tai reiškia dar vieną dalyką, kurį reikia mokytis ir prižiūrėti.

Taip pat, jei jūsų komanda jau turi gerai veikiantį development workflow’ą su kitais įrankiais, perjungimas į Skaffold gali būti ne verta pastangų. Ypač jei jau naudojate kažką panašaus kaip Tilt ar DevSpace. Šie įrankiai sprendžia panašias problemas, tik šiek tiek skirtingais būdais.

Bet jei pastebite, kad praleidžiate daug laiko build’indami ir deploy’indami, jei turite sudėtingą microservice’ų architektūrą, jei norite, kad jūsų local development aplinka būtų kuo artimesnė production’ui – tada Skaffold tikrai verta išbandyti. Pradėkite su paprasta konfigūracija, pamažu pridėkite daugiau feature’ų, kai jų prireikia.

Vienas dalykas, kurį pastebėjau – Skaffold labai gerai veikia su „infrastructure as code” filosofija. Jei jau naudojate Git viskam, jei turite CI/CD pipeline’us, jei jūsų Kubernetes manifest’ai yra version controlled – Skaffold natūraliai įsilieja į šį workflow’ą. Jei dar nedirbate taip, galbūt pirmiau verta susitvarkyti šiuos dalykus.

Ir paskutinis dalykas – dokumentacija. Skaffold dokumentacija yra gana gera, bet kartais reikia pasikasinėti, kad rastumėte tai, ko ieškote. GitHub issues ir discussions taip pat yra naudingi resursai. Bendruomenė yra aktyvi ir dažnai galite rasti atsakymus į savo klausimus arba pavyzdžius, kaip kažką padaryti.

Taigi, ar Skaffold yra silver bullet Kubernetes development’ui? Ne. Ar jis gali labai palengvinti gyvenimą? Absoliučiai. Kaip ir su bet kuriuo įrankiu, raktas yra suprasti, kada jis tinka, o kada ne. Išbandykite jį nedideliame projekte, pamatykite, kaip jis veikia jūsų workflow’ui, ir tada nuspręskite, ar norite jį naudoti plačiau. Dažniausiai tie, kurie jam suteikia šansą, lieka patenkinti rezultatu.

Daugiau

OAuth 2.0 su Keycloak identity server