Obszar DevOps, jego kultura oraz stosowane praktyki ewoluują niezwykle dynamicznie. Dowodem na to jest fakt, że niemal każdego dnia - a niekiedy nawet co godzinę - powstają i wdrażane są nowe narzędzia. Wynika to z prostego powodu: to, co działa w organizacji A, niekoniecznie sprawdzi się w organizacji B. I to jest całkowicie naturalne. Nie istnieje jeden, uniwersalny sposób wdrażania praktyk DevOps w firmie. Istnieje wiele przypadków użycia, a najbardziej praktycznym podejściem jest przyjęcie takich praktyk, które najlepiej sprawdzają się w Twoim zespole - pod warunkiem, że wspierają szybsze dostarczanie oprogramowania oraz wdrażanie opinii użytkowników, a jednocześnie skracają przestoje.
Ta ewolucja przyniosła ze sobą nowe terminy, takie jak DevOps, DevSecOps, a ostatnio również GitOps. Jeśli nie znasz jeszcze tych pojęć:
- DevOps eliminuje granice między zespołami deweloperskimi a operacyjnymi, czyniąc cykl życia aplikacji bardziej zwinny.
- DevSecOps dodaje do tego aspekt bezpieczeństwa, integrując automatyzację i monitorowanie zagrożeń już na etapie tworzenia oprogramowania.
O DevSecOps opowiemy szerzej w innym wpisie, a dziś skupmy się na tym trzecim podejściu – GitOps.
Czym jest GitOps?
GitOps to nowe podejście do wdrażania ciągłego (Continuous Deployment) w aplikacjach cloud-native. Pozwala ono deweloperom korzystać z narzędzi, które już dobrze znają – takich jak systemy kontroli wersji (Git) czy narzędzia CI/CD – aby zautomatyzować zarządzanie infrastrukturą. Cały proces jest mocno zorientowany na potrzeby programistów.
Podstawowa zasada GitOps brzmi: Git jest jedynym źródłem prawdy dla infrastruktury. Oznacza to, że pożądany stan infrastruktury musi być zawsze zapisany w systemie kontroli wersji, co zapewnia pełną przejrzystość oraz możliwość śledzenia każdej zmiany. Wszystkie modyfikacje są rejestrowane - z informacją o autorze, czasie zmiany i identyfikatorze commita. W praktyce oznacza to, że zarówno aplikacja, jak i infrastruktura, stają się wersjonowanymi artefaktami, które łatwo podlegają audytowi.
GitOps opiera się na systemie zarządzania kodem źródłowym opartym o Git, dlatego naturalnymi wyborami są tu GitHub, GitLab czy Bitbucket.
Główna koncepcja GitOps polega na tym, by mieć repozytorium, które zawsze zawiera deklaratywne opisy docelowego stanu infrastruktury lub klastra. Z pomocą procesów automatycznych środowisko (dev, testowe, produkcyjne) jest synchronizowane z tym, co opisane jest w repozytorium Git. W praktyce oznacza to, że chcąc wprowadzić jakąkolwiek zmianę, wystarczy zaktualizować repozytorium - a automatyzacja zajmie się resztą.
Do najpopularniejszych narzędzi wspierających GitOps należą:
- Argo CD (obecnie lider),
- Flux,
- Jenkins X,
- Harness,
- Weaveworks,
- JFrog i wiele innych.
GitOps opiera się na trzech filarach:
- Infrastructure as Code (IaC) – infrastruktura zapisana w kodzie,
- Merge requests (pull requests) – recenzowanie i zatwierdzanie zmian,
- CI/CD – ciągła integracja i dostarczanie.
Sposób, w jaki wdrożysz GitOps w swoim zespole, zależy od tego, co sprawdza się w Twoim konkretnym przypadku. Nie ma jednej właściwej ścieżki.
Typowy workflow GitOps wygląda tak, jak na poniższym diagramie:

Kluczowe zasady workflow GitOps
- Cały system musi być zapisany w sposób deklaratywny.
Wszystkie zasoby powinny być zdefiniowane jako kod, który opisuje, jak system powinien wyglądać. - Pożądany stan systemu musi być przechowywany w systemie kontroli wersji.
Git stanowi pojedyncze źródło prawdy – każda zmiana musi być wersjonowana i widoczna dla całego zespołu. - Aktualizacje muszą być wprowadzane przez merge requesty (MR) i podlegać recenzji oraz zatwierdzeniu.
- Po zatwierdzeniu zmian musi nastąpić automatyczna synchronizacja pomiędzy rzeczywistym stanem systemu a nowym stanem zapisanym w repozytorium.
- Samonaprawianie (self-healing) – każda wybrana platforma GitOps musi mieć zdolność do wykrywania odchyleń i przywracania systemu do zgodnego stanu, nawet jeśli zmiany zostały wprowadzone ręcznie poza repozytorium.
Różnice między DevOps a GitOps
GitOps i DevOps mają wiele wspólnych zasad i podobne cele. DevOps to przede wszystkim zmiana kultury organizacyjnej, która umożliwia lepszą współpracę zespołów deweloperskich i operacyjnych.
Z kolei GitOps dostarcza zespołom narzędzi, które pozwalają wykorzystać praktyki DevOps – takie jak CI/CD, Infrastructure as Code (IaC), oraz kontrola wersji – do pełnej automatyzacji infrastruktury.
Deweloperzy nadal mogą wypychać kod do repozytorium Git, a zespół operacyjny również może wprowadzać zmiany, również korzystając z kodu i Git-a.
Korzyści wynikające z wdrożenia GitOps
Istnieje wiele korzyści z zastosowania GitOps do automatyzacji infrastruktury – od zwiększonej efektywności i bezpieczeństwa, przez szybsze wdrażanie aplikacji, aż po lepszą współpracę zespołów. Oto kilka najważniejszych:
Większa produktywność i szybszy rozwój
Dzięki automatyzacji Continuous Deployment, GitOps pozwala znacząco skrócić MTTD (mean time to deployment). Zespół programistyczny może wdrażać nawet 40 razy więcej zmian dziennie, co przekłada się na większą wydajność całego procesu.
Deweloperzy korzystają z narzędzi, które już dobrze znają – takich jak Git – aby zarządzać wersjami i aktualizacjami funkcjonalności w szybki i spójny sposób. Nie muszą znać szczegółów działania klastra Kubernetes. Ich głównym punktem odniesienia staje się kod w repozytorium, a nie kontenery.
To sprawia, że wdrażanie nowych członków zespołu jest łatwiejsze – mogą osiągać pierwsze efekty już po kilku dniach, a nie miesiącach.
Większa niezawodność
Dzięki Git-owi możliwe jest łatwe przywracanie wcześniejszych stanów systemu (rollback). W przypadku, gdy ktoś przypadkowo wprowadzi ręczną zmianę, która powoduje błąd – można szybko wrócić do ostatniego pożądanego stanu zapisanego w repozytorium.
To poprawia ogólne doświadczenie zespołu deweloperskiego i ułatwia realizację trudnych zadań, takich jak odzyskiwanie po awarii (disaster recovery).
W razie potrzeby można nawet przenieść cały system do innego regionu lub innego dostawcy chmurowego – bez dużego nakładu pracy.
Ulepszony audyt i zgodność z regulacjami
Wykorzystanie workflow Git do zarządzania klastrami Kubernetes wprowadza znacznie wygodniejszy sposób audytowania zmian, które zostały wykonane poza samym klastrem.
Logi zawierają informacje o tym, kto wprowadził zmianę, co dokładnie zostało zmienione oraz znacznik czasu, dzięki czemu wiadomo, kiedy dokładnie dana zmiana została wprowadzona do klastra.
To znacząco ułatwia spełnienie wymogów zgodności, np. SOC 2.
Większa spójność
Ponieważ Git jest jedynym źródłem prawdy zarówno dla aplikacji, jak i infrastruktury, zespół zyskuje spójny, end-to-end workflow.
Nie tylko pipeline’y CI/CD są oparte na pull requestach, ale także wszystkie operacje mogą być w pełni reprodukowane i kontrolowane za pomocą Git-a.
Wyższy poziom bezpieczeństwa
Silne gwarancje poprawności i bezpieczeństwa Git-a oraz wykorzystanie kryptografii przy zarządzaniu zmianami zapewniają bezpieczną definicję pożądanego stanu systemu.
W połączeniu z automatycznymi recenzjami każdego kroku zmiany, GitOps staje się doskonałym sposobem na zabezpieczenie pipeline’ów dostarczania.
W przypadku naruszenia bezpieczeństwa, łatwo jest przeprowadzić audyt i ustalić przyczynę. Można także odtworzyć niebezpieczną wersję systemu w środowisku testowym, by lepiej zrozumieć lukę i szybciej zareagować.
Lepsze operacje
GitOps oferuje pełny, zautomatyzowany pipeline, w którym cały proces CI/CD oparty jest na pull requestach.
Jednocześnie wszystkie zadania operacyjne mogą być również realizowane przez commitowanie zmian w repozytorium Git – bez konieczności wprowadzania ręcznych zmian.
Wyzwania GitOps
Zanim zdecydujesz się na wdrożenie tego nowoczesnego podejścia, warto mieć świadomość, że GitOps nie zawsze jest idealnym rozwiązaniem dla każdego zespołu czy projektu. Jak to często bywa – tam, gdzie są zalety, są też wyzwania.
GitOps wprowadza wiele korzyści, upraszczając cały cykl życia aplikacji i czyniąc go bardziej przyjaznym dla deweloperów. Ale… oznacza to także, że cały zespół musi zaakceptować nowy sposób pracy.
To zmiana, która wymaga dyscypliny i zaangażowania wszystkich członków zespołu. Wiele rzeczy trzeba będzie teraz zautomatyzować i zapisać w kodzie, zamiast konfigurować ręcznie.
Typowy proces zatwierdzania w GitOps wygląda tak:
- Deweloper aktualizuje kod w repozytorium Git.
- Tworzy merge request (MR).
- Osoba zatwierdzająca sprawdza i akceptuje zmiany.
- Zmiana jest automatycznie wdrażana.
Ten “komitetowy” model zmian infrastruktury może być frustrujący dla inżynierów przyzwyczajonych do szybkiego, ręcznego działania.
Dlatego ważne jest, aby cały zespół dokumentował wszystko, co dzieje się w merge requestach i zgłoszeniach (issue). Pokusa, by “szybko coś zmienić na produkcji”, będzie duża - ale im mniej “kowbojskiej inżynierii”, tym lepiej działa GitOps.
Projekt demonstracyjny GitOps
Czas trochę się pobawić i popracować praktycznie. Poniższy projekt demo zostanie zbudowany przy użyciu ArgoCD, które jest obecnie jednym z najlepszych narzędzi GitOps na rynku i bardzo łatwo je uruchomić.
Wymagania wstępne
- Podstawowa znajomość Kubernetes i Dockera
- Znajomość workflow Git
Narzędzia potrzebne
- Docker Desktop
- Repozytorium Git – w tym projekcie użyłem GitLab, aby móc podążać za instrukcją potrzebujesz repozytorium publicznego, żeby ArgoCD mogło synchronizować się bez błędów. Możliwe jest używanie repozytorium prywatnego, ale wymaga to dodatkowej konfiguracji.
- Minikube – demo będzie uruchamiane lokalnie na moim komputerze. W kolejnych wpisach pokażemy, jak korzystać z AWS EKS.
- Przeglądarka internetowa – potrzebujemy dostępu do GUI ArgoCD, które zapewnia szczegółowy widok naszych wdrożeń i konfiguracji klastra.
Czas na zabawę!
Zakładam, że masz już wszystkie powyższe narzędzia zainstalowane i gotowe, więc pominę instrukcje ich instalacji.
Pierwszą rzeczą, którą musimy zrobić, jest zainstalowanie ArgoCD w naszym klastrze. W tym celu najpierw musimy utworzyć namespace dla ArgoCD.
~ kubectl create namespace argocd
~ kubectl apply -n argocd -f
https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
Powyższe dwa polecenia w zasadzie tworzą namespace argocd
, który będzie przechowywał zasoby usług i aplikacji, których potrzebujemy.
Po wykonaniu tych poleceń powinniśmy być w stanie wyświetlić listę uruchomionych podów za pomocą poniższego polecenia:
kubectl get pods -n argocd
To polecenie wyświetla wszystkie pody działające w wcześniej utworzonym namespace o nazwie argocd, tak jak na poniższym obrazku:

Spróbujmy teraz wyświetlić listę działających usług.
kubectl get svc -n argocd
Powyższa komenda wyświetli listę wszystkich usług działających w tym samym namespace o nazwie argocd.
Jeśli wynik będzie wyglądał podobnie do poniższego, możesz uzyskać dostęp do interfejsu webowego.

Aby uzyskać dostęp do interfejsu webowego, musimy przekierować port usługi wyróżnionej na obrazku na port 8080 na naszej lokalnej maszynie, wykonując poniższe polecenie:
kubectl port-forward -n argocd svc/argocd-server 8080:443
To polecenie wyświetli adres IP, pod którym możesz uzyskać dostęp do interfejsu webowego ArgoCD.
Skopiuj ten adres i wklej go w przeglądarce. Jeśli wszystko jest poprawnie skonfigurowane, zobaczysz stronę logowania do ArgoCD, podobną do poniższej:

Możesz się zastanawiać, jakie są dane logowania. Są one domyślnie ustawione.
Nazwa użytkownika to admin, a hasło jest zapisane jako sekret o nazwie argocd-initial-admin-secret, który został utworzony podczas konfiguracji ArgoCD.
Aby pobrać ten sekret, wystarczy uruchomić poniższe polecenie:
kubectl get secret argocd-initial-admin-secret -n argocd -o yaml
To zwróci dane w formacie YAML zawierające hasło

Możesz uzyskać hasło w postaci zwykłego tekstu, uruchamiając
echo YOUR_PASSWORD | base64 --decode
Jeśli wpiszesz nazwę użytkownika i hasło, powinieneś móc się pomyślnie zalogować.

Drugą rzeczą, którą musimy zrobić, jest skonfigurowanie projektu i wypchnięcie go do naszego własnego repozytorium git. Ponownie zakładam, że już wiesz, jak to zrobić, więc po prostu wymienię, czego potrzebujemy (struktura plików).
- Utwórz katalog w projekcie i nadaj mu nazwę dowolnego środowiska. Ja nazwę swój development.
- W tym katalogu utwórz dwa pliki -
deployment.yaml
iservice.yaml
.
Dla naszego pliku deployment.yaml, skopiuj i wklej poniższy kod:
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitops-demo-app
spec:
selector:
matchLabels:
app: git-ops-app
replicas: 2
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: fessywonder/golang:1.0
ports:
- containerPort: 8080
Dla naszego pliku service.yaml, skopiuj i wklej poniższy kod:
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
ports:
- port: 8080
protocol: TCP
targetPort: 8080
Potrzebujemy powyższych plików, aby skonfigurować nasz klaster i aplikację. Musimy jednak również skonfigurować ArgoCD w naszym klastrze.
Aby to zrobić, należy utworzyć kolejny plik. Możesz go nazwać app.yaml i wkleić do niego poniższy kod:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myargo-application
namespace: argocd
spec:
project: default
source:
repoURL: https://gitlab.com/t9151/gitops-blog-post.git
targetRevision: HEAD
path: dev
destination:
server: https://kubernetes.default.svc
namespace: myapp
syncPolicy:
syncOptions:
- CreateNamespace=true
automated:
selfHeal: true
prune: true
Uwaga: Projekt musi zostać wypchnięty do naszego źródła prawdy (Single Source of Truth), ponieważ potrzebujemy adresu URL repozytorium do konfiguracji ArgoCD w klastrze. Obraz używany w pliku deployment.yaml oraz adres repoURL
w pliku app.yaml odnoszą się do publicznego obrazu z Docker Huba oraz projektu z GitLaba, które są moją własnością. Dopóki będą one dostępne, konfiguracja będzie działać. W przeciwnym razie możesz podmienić je na własne lub wyszukać inne dostępne obrazy w Docker Hubie. Możesz też sklonować istniejące repozytorium zamiast tworzyć własne.
W tym momencie jesteśmy gotowi, by zastosować konfigurację i utworzyć naszą aplikację oraz zasoby. Można to zrobić za pomocą polecenia:
kubectl apply -f app.yaml
Po jego wykonaniu otrzymasz informację, że aplikacja została utworzona. Po powrocie do interfejsu użytkownika ArgoCD zobaczysz widok podobny do poniższego:

Używany obraz to oficjalny obraz golanga i nie zawiera wielu komponentów.
Aby zobaczyć ArgoCD/GitOps w akcji, zmień coś w jednym z plików (np. nazwę aplikacji), zatwierdź zmiany i wypchnij do repozytorium. ArgoCD ma wbudowaną funkcję samonaprawy (self-healing), którą włączyliśmy w pliku konfiguracyjnym. Jest w stanie wykonywać kontrole stanu (status checks / health checks) i poinformować nas, gdy coś pójdzie nie tak. ArgoCD wykryje zmiany w ciągu około 3 minut i automatycznie zsynchronizuje stan klastra. Zobaczysz status synchronizacji, szczegóły commita i czas wykonania. Jeśli ręcznie zmienisz wdrożenie lokalnie, ArgoCD wykryje tę zmianę i w ciągu kilku sekund przywróci stan zapisany w repozytorium.