MLOPS w chmurze – jak skutecznie wdrażać modele AI w środowisku chmurowym

08.04.2026|  Joanna Szych

Wstęp

Wdrożenia modeli sztucznej inteligencji i wdrożenia aplikacji w środowisku chmurowym to w ostatnim czasie dwa popularne obszary działań wielu firm. W pracy jako MLOps, często łączymy oba te zagadnienia wdrażając „w chmurze” aplikacje udostępniające rozwiązania AI, tak aby inni użytkownicy mogli je w prosty sposób wykorzystywać. W poniższym artykule, przedstawiam kilka aspektów naszej pracy, które pomagają wdrażać nowe rozwiązania AI szybko i skutecznie. Wiedza ta może być przydatna dla osób na podobnych stanowiskach i współpracujących z MLOps, ale także dla pasjonatów, którzy chcą dowiedzieć się więcej o tym, jak wygląda proces wdrażania nowych rozwiązań. Opisane tematy bazują na doświadczeniach z pracy nad wieloma projektami i pokazują, jak dzięki ujednoliconym narzędziom i procesom można znacząco przyspieszyć uruchamianie nowych modeli oraz uprościć ich utrzymanie. 

Rola MLOps

Punktem startowym każdego wdrożenia, jest pomysł na przeznaczenie modelu (czyli, co dany model powinien robić) i w jakim obszarze możemy go wykorzystać. Modele AI najczęściej wplatane są w część procesów biznesowych jako usprawnienie i pomoc dla analityków, konsultantów, czy developerów obsługujących dany proces. W związku z tym, na początku drogi większość pracy leży po stronie Analityków Biznesowych, którzy zbierają wymagania i dopasowują najlepsze rozwiązanie, oraz Data Science, którzy trenują i przygotowują model, a także weryfikują jego skuteczność w procesie. Natomiast rolą MLOps jest takie przygotowanie i osadzenie modeli w środowisku produkcyjnym, aby mogły działać w realnych procesach i skalować się wraz z rosnącym wykorzystaniem. 

Cykl życia modelu sztucznej inteligencji oraz podziału zadań między zespoły Data Science oraz MLOps został w uproszczeniu przedstawiony na poniższym schemacie. Należy jednak pamiętać, że podział ten jest tylko poglądowy, a realne zadania należące do obu tych grup mogą się lekko różnić w zależności od ustaleń. Natomiast część zadań realizowana jest najefektywniej, gdy obie strony współpracują nad ich wykonaniem. 

Pierwsze zadania MLOps’a często pojawiają się w momencie projektowania tego jak najlepiej połączyć model z obecnymi procesami biznesowymi. W środowisku chmurowych wdrażamy modele działające w trybie real-time, które mają za zadanie wykonać predykcję oraz wysłać odpowiedź jak najszybciej po otrzymaniu zapytania. W związku z tym przed podjęciem działań wdrożeniowych niezbędne jest zrozumienie oczekiwań różnych stron zaangażowanych w proces i skonfrontowanie ich z możliwościami technologicznymi. Dlatego początkiem każdego projektu jest uczestniczenie w dyskusjach na tematy takie jak, wymagany rodzaju komunikacji między komponentami, czy zasady i ograniczenia dotyczące przetwarzania i przechowywania danych koniecznych do działania modelu. Dopiero w dalszej kolejności zajmujemy się przygotowaniem odpowiednich środowisk, zbudowaniem obrazów z aplikacją czy testami. Ostatnim krokiem na liście wdrożeniowych zadań, jest oczywiście produkcyjne udostępnienie modelu, jednak nie jest to równoznaczne z końcem pracy. Wdrożone rozwiązania wymagają stałego utrzymania, które obejmuje między innymi weryfikację podatności czy monitoring działania modelu, co w przypadku wykorzystania modeli Machine Learning często wymaga innego podejścia niż w przypadku standardowych aplikacji. Przez cały czas życia modelu, obserwujemy takie aspekty i w razie konieczności poprawek ściśle współpracujemy z zespołami Data Science, aby zapewnić jak największe korzyści dla użytkowników biznesowych.

Wymagania technologiczne

Tak jak pisaliśmy wyżej, do każdego przypadku wdrożenia podchodzimy indywidualnie i analizujemy wszystkie jego aspekty. Jednak, dzięki temu, że środowisko wdrożeniowe jest podobne dla wszystkich modeli działających ‘real-time’, duża część procesu może zostać zautomatyzowana. Poniżej, przedstawiam zarys głównych wymagań technologicznych, które stale nam towarzyszą. 

Środowisko chmurowe

Wszystkie modele działające w trybie real‑time uruchamiane są w środowisku chmurowym Google Kubernetes Engine (GKE). GKE zapewnia stabilną i skalowalną infrastrukturę, która umożliwia szybkie reagowanie na zmiany oraz łatwe zarządzanie wieloma aplikacjami równolegle. Dzięki konteneryzacji (pakowaniu aplikacji wraz ze środowiskiem w lekkie, odizolowane kontenery) możemy w spójny sposób uruchamiać różne modele, mając pełną kontrolę nad zasobami, aktualizacjami oraz izolacją środowisk. Kubernetes stanowi fundament całego procesu wdrożeniowego i pozwala na automatyzację wielu kroków, które są wspólne dla wszystkich modeli. Dodatkowym autem oparcia procesu o to rozwiązanie, jest jego szerokie wykorzystanie i dostępność w środowisku IT, co w razie konieczności pozwoli na sprawną zmianę na przykład dostawców chmurowych, lub przejście na „on-premise”.

Komunikacja

Z uwagi na architekturę istniejących już aplikacji i zdefiniowane schematy, najczęstszym wymaganiem jest, aby model można było odpytać korzystając z komunikacji synchronicznej po REST API. Dzięki temu, główny proces może wysłać proste zapytanie np. w schemacie JSON z danymi potrzebnymi do przeprowadzenia predykcji i otrzymać wynik tą samą ścieżką. Czasami jednak niezbędne jest zastosowanie komunikacji asynchronicznej z wykorzystaniem Apache Kafka. Jednym z takich przypadków, może być sytuacja, w której aplikacja wysyłająca zapytanie do modelu, nie potrzebuje jego odpowiedzi, natomiast dana predykcja powinna zostać przesłana w inne miejsca. Niezależnie od wybranej formy komunikacji, ich obsługa jest jedną z rzeczy, które są powtarzalne przy każdym nowym wdrożeniu. 

Logika biznesowa

Model AI rzadko działa jako samodzielny komponent. W praktyce do poprawnego zwrócenia predykcji często wymagane są dodatkowe funkcjonalności. Zazwyczaj są to działania takie jak pobieranie plików, zwracanie wartości domyślnych w określonych sytuacjach czy integracja z bazami danych. Zdarza się również, że ten sam model musi być używany w wielu różnych procesach, co wymaga elastycznej architektury pozwalającej na wielokrotne wykorzystanie kodu bez jego duplikacji.

Podsumowując, mimo że każdy model odpowiada na inne potrzeby biznesowe, wymagania technologiczne związane z jego wdrożeniem - komunikacja, logika aplikacji, integracje oraz uruchamianie w środowisku GKE - pozostają w dużej mierze powtarzalne. Ta wspólna baza stała się fundamentem do standaryzacji całego procesu.

ModelWrapper

Wraz z rosnącą liczbą wdrażanych modeli pojawiła się potrzeba ujednolicenia oraz przyśpieszenia sposobu udostępniania aplikacji. Te z funkcji, które powtarzają się przy wielu wdrożeniach modeli postanowiliśmy wydzielić w formie biblioteki napisanej w języku Python, o nazwie ModelWrapper. Jej głównym celem jest automatyzacja pracy zespołów MLOps oraz Data Science, poprzez zdefiniowanie wspólnych standardów oraz usprawnienie utrzymania kodu. Ideą działania biblioteki jest otoczenie kodu dostarczonego przez Data Scientis zbiorem wspólnych schematów, które będę działać tak samo niezależnie od projektu. 

Podstawowe zadanie, które realizuje ModelWrapper to zbudowanie aplikacji opartej o framework FastAPI oraz zdefiniowanie odpowiednich endpointów (adresów w API wywołujących konkretne funkcje aplikacji), które pozwolą na odpytanie modelu. Każdy endpoint wywołuje konkretną funkcję w projekcie Data Scientisty, dzięki czemu osoba rozwijająca model może skupić się wyłącznie na implementacji logiki predykcji oraz dodatkowych funkcji biznesowych. W praktyce oznacza to, w każdym nowym projekcie powinniśmy przestrzegać konkretnego nazewnictwa części plików i funkcji oraz dodać ModelWrapper do zależności. Dzięki temu, poprzez odpowiednie uruchomienie aplikacji pythonowej możemy wykonywać dedykowaną dla projektu logikę, podczas wywołania danego endpointu.

Na tym etapie, warto również wspomnieć jakie inne funkcjonalności, poza definicją aplikacji FastAPI, dostarczane są w ModelWrapperze. Są tą, między innymi, rozwiązania dotyczące:

  • obsługi plików konfiguracyjnych dla wielu środowisk,
  • formatowania logów, 
  • zarządzania błędami,
  • integracji z bazami danych i zewnętrznymi komponentami,
  • obsługi certyfikatów i zabezpieczenia połączeń,
  • odczytywania wartości z sekretów.

Dużą część biblioteki stanowią również funkcje dedykowane do zarządzania komunikacją poprzez Apache Kafka. W niektórych procesach wymagane będzie tylko odbieranie wiadomości z tego źródła, w innych tylko wysyłanie wiadomości, a jeszcze inne będą potrzebować obu tych funkcjonalności. Dzięki ModelWrapperowi, w przypadku odbierania wiadomości z Kafka, Data Scientista musi jedynie uzupełnić plik konfiguracyjny o odpowiednią nazwę topicu na którym będzie oczekiwać wiadomości, a w przypadku wysyłki wiadomości podać nazwę topiku oraz wywołać odpowiednią funkcję w swoim kodzie. Cała reszta, jak weryfikacja i konfiguracja połączeń są zaimplementowane w bibliotece. 

Dodatkowym aspektem biblioteki ModelWrapper jest także wsparcie oraz usprawnienie lokalnej pracy nad aplikacjami. Część opisanych funkcjonalności np. korzystanie z bazy danych, wymaga połączenia do zewnętrznych elementów. Przy docelowym działaniu aplikacji, komponenty te są odpowiednio powołane i dostępne w środowisku chmurowym. Natomiast podczas pracy nad projektem na środowisku lokalnym Data Scientiści często nie mają dostępu do niektórych komponentów lub muszą uruchamiać dodatkowe kontenery które zastąpią wymagane elementy. Aby w takich wypadkach ułatwić i przyspieszyć proces developmentu, ModelWrapper zawiera także szereg modułów, które symulują zewnętrzne procesy, np. wspomniane połączenie do bazy danych czy połączenie do obiektów typu „bucket”. Dzięki takiemu działaniu, praca w środowisku lokalnym może przebiegać sprawniej. 

Ujednolicony deployment. Jeden template = Wiele modeli

Opisana powyżej biblioteka ModelWrapper zapewnia spójny sposób tworzenia oraz działania aplikacji udostępniających modele AI. Poza korzyściami płynącymi z szybkości przygotowania takiej aplikacji, pozwala to również na dużą automatyzacje oraz ujednolicenie procesu deploymentu (udostępnienia) modeli. Każdy nowy projekt może wykorzystywać te same mechanizmy budowy obrazu, konfiguracji i wdrażania w środowisku chmurowym, niezależnie od rodzaju modelu i jego logiki biznesowej.

Budowa obrazu

Tak jak zostało wspomniane, ModelWrapper oraz projekt przygotowany przez Data Scientiste łączą się ze sobą, razem tworząc kod aplikacji, która zostanie udostępniona odbiorcom. Docelowo aplikacja uruchamiana jest w środowisku kubernetes’owym, a dokładniej na Google Kubernetes Engine. W związku z tym do jej udostępniania potrzebujemy jeszcze obrazu Dockerowego ze zbudowaną aplikacją oraz definicji kontenerów, które mają zostać utworzone. Dzięki wcześniejszemu ujednoliceniu procesu do budowy takiego obrazu dla każdego z modeli, możemy skorzystać z wcześniej przygotowanych definicji dockerfile oraz schematów pipeline. Oczywiście, muszą one być odpowiednio parametryzowane, ze względu na takie informacje jak nazwa modelu i nazwa obrazu, repozytorium, z którego chcemy pobrać kod czy wersja pythona na której będziemy bazować. Dodatkowym aspektem jest także docelowe urządzenie, na którym będą wykonywane przeliczenia, czyli wybór środowiska tylko z CPU lub także z GPU (kartą graficzną) – te dwie opcje potrzebują swoich dedykowanych dockerfiles. Proces budowania obrazu został pokrótce przedstawiony na poniższym schemacie. Jak widać poza pobraniem i załadowaniem plików z repozytorium i budową obrazu dockerowego są dodatkowe kroki takie jak skanowanie kodu i testowanie rozwiązania, które zostały opisane dokładniej w jednej z poniższych sekcji. Końcowym krokiem pipeline jest zapisanie obrazu do specjalnego rejestru, z którego później będzie można go w każdej chwili pobrać.

Deployment obrazu

Gdy już mamy gotowy obraz możemy zająć się przygotowaniem go do deploymentu, czyli zainstalowania w dedykowanym środowisku chmurowym oraz udostępnienia odbiorcom. W tym celu również wystarczy nam jedna przygotowana definicja pipeline ze zdefiniowanymi krokami do wykonania, jednak potrzebujemy zdecydowanie więcej opcji parametryzacji. Podczas przygotowywania wdrożenia musimy zdefiniować parametry takie jak:

  • ilość zasobów CPU i pamięci RAM oraz ilość instancji
  • nazwy niezbędnych sekretów i plików konfiguracyjnych
  • konfiguracje dotyczące weryfikacji zdrowia aplikacji (health check)
  • konfiguracja dotycząca bazy danych i używanych bucketów
  • konfiguracja dotycząca dostępu do danych endpointów
  • konfiguracje dotyczące dodatkowych funkcjonalności, jak cronjob czy zadania inicjalizacyjne
  • i wiele innych, zależnych od konkretnego przypadku wdrożenia

Oczywiście ze względu na liczbę modeli, dla których taka konfiguracja jest potrzebna, oraz częstotliwość uruchamiania pipeline’ów, niezbędne jest, aby wszystkie informacje były odpowiednio zapisane i automatycznie uzupełniane podczas wykonywania kroków pipeline. W tym celu, wykorzystane zostało narzędzie HELM, które pozwala na przygotowanie definicji wdrożenia z użyciem parametryzacji w takim sposób, aby niezbędne zmienne mogły być zaciągane ze specjalnie zdefiniowanych i uszeregowanych plików. Dzięki temu podczas definiowania pipeline dla danego modelu, wystarczy wskazać z których plików należy skorzystać, a cała konfiguracja zostanie automatycznie przygotowana. Pozwala to na obsługę wielu projektów równolegle, minimalizując koszty utrzymania i ryzyko błędów. Poniższy diagram przedstawia główne kroki pipeline’u pozwalającego wdrożyć naszą aplikację na środowisko chmurowe. Warto jednak zaznaczyć, że wdrożenia te zawsze odbywają się w ustalonej kolejności od środowiska developerskiego, przez testowe i akceptacyjne aż po produkcyjne. Takie podejście, pozwala zarówno na udostępnienie przestrzeni do testowania zmian, jak i na dużą kontrolę tego co trafia na środowisko produkcyjne.

Oddzielne wersjonowanie kodu aplikacji i modelu ML

Celem opisanego powyżej procesu deploymentu jest udostępnienie aplikacji, która na żądanie wykona predykcje modelu AI, oraz odeśle odpowiedź w ustalonym schemacie. Sam model uczenia maszynowego jest jednak osobnym komponentem i tylko jedną z części całej aplikacji. Tak jak opisano powyżej logika działania aplikacji przygotowywana jest przez Data Scientiste i dostarczana w dedykowanym repozytorium kodu, natomiast sam model jest zazwyczaj trenowany osobno i dostarczany na przykład w postaci pliku pickle. W ramach kodu aplikacji taki plik jest później w odpowiedni sposób ładowany, tak aby wykonać predykcje.

Zmiany w samym modelu są niezależne od zmian w kodzie aplikacji – obie części mogą być modyfikowane jednocześnie, ale dużo częściej zdarza się, że tylko jedna z nich ulega zmianie. Ze względu na to, a także na duże rozmiary modeli oraz wymagania dotyczące odpowiedniego wersjonowania informacji o nich, pliki z modelami nie są częścią budowanego obrazu dockerowego. Przechowywane są one w odpowiednim narzędziu pozwalającym na ich zarządzanie oraz wersjonowanie. Natomiast, podczas wdrażania na środowisko i udostępniania aplikacji z modelem, wskazujemy zarówno wersję obrazu z kodem aplikacji jak i wersję modelu, który w trakcie działania pipeline pobierany jest np. do odpowiedniego bucketu i z tego miejsca zaczytywany jako część uruchamiania aplikacji.

Takie rozdzielenie tych części, pozwalana także na proste wkomponowanie w proces użycia modeli GenAI udostępnianych w ramach usługi Google VertexAI, które również są wykorzystywane w niektórych projektach. Modele te nie są wtedy uruchamiane wewnątrz aplikacji, lecz w ramach jej działania odpytywane jest dedykowane API VertexAI, które wykonuje predykcję. 

Testowanie i bezpieczeństwo modelu

Stabilność oraz bezpieczeństwo działania udostępnionych rozwiązań to jedne z kluczowych aspektów pracy nad wdrożeniami. Zgodnie z procedurami dotyczącymi wszystkich wdrożeń aplikacji w banku, przed uruchomieniem do użytku w środowisku produkcyjnym dane rozwiązanie musi przejść przez szereg kontroli potwierdzających jego gotowość. Weryfikowane są one między innymi pod kątem użytych rozwiązań technologicznych, czy odpowiednich zabezpieczeń. Dodatkowo, przygotowany model oraz jego wyniki muszą zostać także poddane walidacji i zaakceptowane do wdrożenia z perspektywy biznesowej, tak aby na pewno usprawniały procesy, w ramach których będą użyte.

Natomiast, ważną częścią utrzymania każdej z aplikacji wraz z modelami AI są także ciągłe testy zawiązane z poprawnością odpowiedzi oraz bezpieczeństwem, które pozwalają na wykrycie szkodliwych zmian na wczesnym etapie. Aby to osiągnąć, zarówno podczas prac developerskich jak i już po wdrożeniu wykonywane są regularne weryfikacje stosowane jako kroki w pipeline, które sprawdzają:

  • podatności pochodzące z zewnętrznych bibliotek,
  • podatności pochodzące z kodu źródłowego aplikacji,
  • poprawność odpowiedzi na przykładowe zapytanie.

Wszystkie aspekty są weryfikowane zarówno już podczas budowy pierwszego obrazu, jak i koniecznie przed każdym wdrożeniem produkcyjnym. Szczególnie w przypadku podatności z zewnętrznych bibliotek, bardzo ważne jest, aby zostały one sprawdzone dwukrotnie, ze względu na ich dynamiczny charakter wykrywania. Podczas budowy obrazu w poniedziałek, możemy nie wykryć żadnych niebezpiecznych komponentów, jednak podczas próby jego deploymentu w środę może okazać się, że zostały znalezione nowe podatności w jednej z użytych bibliotek. Skanowanie obrazu przed wdrożeniem pomaga zapobiegać sytuacji, w której udostępnimy na środowisku produkcyjnym aplikację z luką bezpieczeństwa, natomiast dodatkowe skanowanie podczas budowy obrazu pozwala na szybką reakcję już podczas developmentu. Trzeba również wziąć pod uwagę wyzwania związane z wyprowadzaniem podatności w bibliotekach użytych bezpośrednio do budowy modelu. Zdarza się ze nowe wersje takich bibliotek wprowadzają duże zmiany związane z wykonywaniem obliczeń, co może mieć znaczący wpływ na działanie modelu i poprawność predykcji, a także prowadzić nawet do konieczności ponownego treningu. Ze względu na takie sytuacje proces opiekowania podatności wymaga zaangażowania zarówno po stronie zespołu MLOps jak i Data Science.

Poza regularnym dbaniem o bezpieczeństwo aplikacji, drugim ważnym aspektem są testy poprawności. Testy weryfikują czy dany projekt nadal spełnia swoje założenia, takie jak ustalony format odpowiedzi czy w przypadku niektórych modeli poprawność predykcji na przykładowe zapytania. Data Scientis ma możliwość zdefiniowania takich testów w repozytorium projektu poprzez przygotowanie całego pliku z testami we frameworku pytest lub poprzez zdefiniowanie przykładowych zapytań i odpowiedzi, które posłużą do uruchomienia testów przygotowanych w ramach ModelWrapper. Tak samo jak skanowanie podatności, takie testy mogą być wykonane na dwóch etapach:

  • tuż po zbudowaniu obrazu odpytując bezpośrednio sam obraz dockerowy,
  • już po wgraniu obrazu na środowisko developerskie/testowe wykorzystując realną konfigurację aplikacji.

Chcąc udostępnić nową wersję aplikacji produkcyjnej, wymagane jest, aby przeszła ona podstawowe testy poprawności. Weryfikacja podczas działania pipeline wdrożeniowego, pozwala na automatyzację tego warunku - jeśli testy nie zostaną zakończone poprawnie, dalsze kroki pipeline mogą zostać zatrzymane tak, by niepoprawna wersja nie dotarła do kolejnych środowisk. Dzięki takiemu podejściu, mamy pewność, że nawet najmniejsze usprawnienia w kodzie czy zmiany takie jak użycie nowszych wersji bibliotek nie wpłyną na poprawne działanie systemu. Oczywiście jest to tylko jedno z zabezpieczeń, a cały proces wykorzystania modelu powinien być regularnie nadzorowany np. poprzez specjalne narzędzia do monitoringu pozwalające określić jego użyteczność czy zmiany w przetwarzanych danych.

Podsumowanie

Przy wdrożeniach rozwiązań wykorzystujących sztuczną inteligencję, często zależy nam na bardzo dobrej jakości predykcji, która realnie usprawnia procesy. Natomiast, przy dużej skali takich rozwiązań, równie ważny jest szybki czas ich dostarczenia, tak, aby jak najwięcej procesów mogło zostać usprawnionych. Kluczową rolę odgrywają tutaj standaryzacja rozwiązań, automatyzacja procesów oraz zapewnienie skalowalnej infrastruktury, która umożliwia szybkie i bezpieczne uruchamianie nowych projektów. Wprowadzenie biblioteki ModelWrapper znacząco usprawnia ten proces, zapewniając wspólne schematy działania aplikacji, ujednolicone mechanizmy komunikacji, obsługę konfiguracji i logów, a także gotowe integracje z usługami chmurowymi i narzędziami takimi jak Apache Kafka, FastAPI czy systemy przechowywania danych.

Dzięki wykorzystaniu konteneryzacji, Google Kubernetes Engine oraz parametryzowanych pipeline’ów opartych o HELM, wdrażanie modeli staje się przewidywalne, powtarzalne i odporne na błędy. Rozdzielenie wersjonowania kodu aplikacji i samego modelu zapewnia elastyczność, a jednocześnie pozwala lepiej kontrolować zmiany wpływające na działanie systemu. Całość dopełniają rozbudowane mechanizmy testowania - od skanowania bezpieczeństwa po testy poprawności predykcji - gwarantujące utrzymanie wysokiej jakości wdrażanych rozwiązań. Dzięki takiemu podejściu możemy budować środowisko, które z jednej strony wspiera tempo pracy zespołów, a z drugiej zapewnia stabilność i bezpieczeństwo niezbędne do produkcyjnego wykorzystania modeli AI.