Argo CD i Kubernetes: automatyczne wdrożenia z kontrolą zmian

0
126
3.8/5 - (5 votes)

Nawigacja:

Dlaczego Argo CD i GitOps zmieniają sposób wdrażania na Kubernetesie

Od kubectl apply do kontrolowanych wdrożeń

Czy Twoje wdrożenia na Kubernetes wciąż opierają się na serii komend kubectl apply -f i ręcznych poprawkach YAML-i? W małym zespole to jakoś działa, ale przy kilku środowiskach i kilkunastu usługach łatwo o chaos: nikt nie wie, jaki aktualnie jest stan klastra, a „hotfix na produkcji” zrobiony z laptopa admina żyje tylko w pamięci tego admina.

Tradycyjne podejście to:

  • zmiana manifestu lokalnie,
  • commit do Gita (jeśli ktoś pamięta),
  • ręczne odpalenie kubectl na odpowiednim kontekście,
  • czasem modyfikacja „na żywca” przez kubectl edit w nagłej sytuacji,
  • brak pełnego audytu, co kiedy i gdzie poszło.

Taki proces jest słabo powtarzalny, trudny do odtworzenia na nowym klastrze i praktycznie nie daje gwarancji, że stage i production są faktycznie zbieżne. Do tego dochodzi problem „ręcznych poprawek” w klastrze, które nie trafiają do repozytorium – pojawia się dryf konfiguracyjny.

Idea GitOps: jedno źródło prawdy i ciągła synchronizacja

GitOps zakłada, że cały pożądany stan klastra Kubernetes jest opisany deklaratywnie w repozytorium Git. To repozytorium staje się jedynym źródłem prawdy. Klaster nie jest miejscem, gdzie „ręcznie coś się klika”, ale jedynie odzwierciedleniem tego, co zapisane w Git.

Jak to działa w praktyce?

  • Opisujesz aplikacje, konfigurację i polityki w plikach YAML/JSON (lub generujesz je np. z Helm/Kustomize).
  • Składasz wszystko w repozytorium Git – z czytelną strukturą katalogów.
  • System GitOps (tu: Argo CD) obserwuje repozytorium i porównuje je ze stanem klastra.
  • Każda zmiana w Git jest traktowana jak żądanie zmiany w klastrze i może wywoływać automatyczne wdrożenie.
  • Jeżeli ktoś zmienia coś ręcznie w klastrze, Argo CD wykrywa dryf i może go cofnąć.

Zauważ, jak zmienia się myślenie: zamiast „wchodzę na klaster i zmieniam”, przyjmujesz podejście „robię pull requesta, a kontroler dba o resztę”. Deployment staje się zwykłą zmianą w kodzie, ze wszystkimi korzyściami: review, historia zmian, rewizje, możliwość szybkiego diffu między wersjami.

Push vs pull: klasyczne CI/CD a GitOps

Klasyczne podejście CI/CD do Kubernetesa opiera się najczęściej na push:

  • pipeline (np. w Jenkins, GitLab CI, GitHub Actions) po zbudowaniu obrazu łączy się z API serwera Kubernetesa,
  • ma uprawnienia do wykonywania kubectl apply lub używa API klienta,
  • pipeline „pcha” zmianę do klastra.

Model GitOps z Argo CD działa na zasadzie pull:

  • Argo CD ma skonfigurowane repozytoria Git i klastry docelowe,
  • obserwuje Git (polling lub webhooki),
  • w momencie zmiany sam „ściąga” pliki i porównuje ze stanem klastra,
  • jeśli polityka na to pozwala, samodzielnie wykonuje synchronizację.

Pipeline CI kończy się zwykle na zbudowaniu i opublikowaniu obrazu kontenera oraz aktualizacji manifestów w Git (np. zmiana tagu obrazu). Wdrożeniem zajmuje się Argo CD w klastrze, który wie najlepiej, w jakim jest stanie, jakie polityki obowiązują i jak ma wyglądać docelowa konfiguracja.

Rola Argo CD jako kontrolera stanu klastra

Argo CD zachowuje się jak kontroler stanu specyficzny dla Twoich aplikacji:

  • regularnie pobiera definicje aplikacji z repozytorium Git,
  • porównuje „desired state” (to, co w Git) z „actual state” (to, co w klastrze),
  • sygnalizuje różnice w UI, API i przez notyfikacje,
  • potrafi wykonać synchronizację – ręczną lub automatyczną – aby doprowadzić klaster do stanu zgodnego z Git.

Do tego dochodzą mechanizmy typu auto-prune (usuwanie zasobów, których już nie ma w repozytorium) oraz self-heal (przywracanie „nadpisanej” konfiguracji w klastrze). Efekt: mniej niespodzianek, mniej „tajemniczych różnic” między środowiskami, lepsza obserwowalność zmian.

Czy production i stage naprawdę są takie same?

Jak często zdarzało Ci się usłyszeć: „ale przecież na stage działało…” – a potem okazywało się, że na produkcji ktoś kiedyś zmienił limit zasobów albo zmodyfikował ConfigMapę z poziomu konsoli? GitOps z Argo CD wymusza inną dyscyplinę: klaster jest odzwierciedleniem Git. Jeśli stage i prod mają mieć taki sam setup, różnice muszą być widoczne w repozytorium, a nie w tajemnych komendach „na szybko”.

Pytanie do Ciebie: ile dziś masz miejsc, w których przechowujesz konfiguracje Kubernetesa? Jeden repozytorium? Trzy? A może część w Git, część w Wiki, część w notatniku SRE? To dobry moment, żeby zdecydować, gdzie chcesz mieć jedyne źródło prawdy.

Fundamenty – Kubernetes, manifesty i podejście deklaratywne

Jakie zasoby Kubernetesa kontroluje Argo CD

Argo CD nie jest magicznym narzędziem „do wszystkiego”. Działa w warstwie, w której Kubernetes przetwarza swoje manifesty. Jego praca sprowadza się do: „co jest opisane w pliku, ma się znaleźć w klastrze”. W praktyce Argo CD operuje na:

  • podstawowych obiektach: Deployment, StatefulSet, DaemonSet, Job, CronJob,
  • sieci: Service, Ingress, Gateway API (jeśli masz CRD),
  • konfiguracji: ConfigMap, Secret (z ograniczeniami, np. szyfrowanie/sealed-secrets),
  • zasobach klastrowych: Namespace, Role, ClusterRole, RoleBinding, NetworkPolicy,
  • CRD i zasobach niestandardowych – wszystko, co rozumie apiserver Kubernetesa.

Argo CD czyta manifesty z Git, generuje „renderowany” zestaw obiektów (np. z Helm lub Kustomize), a następnie porównuje go z tym, co w danej chwili istnieje w klastrze. Różnice są wizualizowane i mogą być automatycznie korygowane.

Deklaratywne vs imperatywne zarządzanie klastrem

Imperatywne podejście: mówisz klastrowi, jakie akcje wykonać:

  • kubectl create – utwórz zasób,
  • kubectl delete – usuń zasób,
  • kubectl scale – zmień liczbę replik,
  • kubectl edit – zmodyfikuj aktualną definicję.

W takim modelu operacje są sekwencją komend, a odtworzenie stanu wymaga powtórzenia tej sekwencji. Często jest to zapisane w czyjejś głowie lub w kilku skryptach Bash.

Deklaratywne podejście: opisujesz jaki ma być stan końcowy, a nie listę kroków. Manifest Deploymentu mówi: „ma być aplikacja X, z 3 replikami, limitem zasobów takim i takim, konfiguracją Y”. Kubernetes bierze ten opis i stara się doprowadzić klaster do zgodności z nim. Argo CD rozszerza to o aspekt wersjonowania i utrzymania zgodności ze źródłem (Git).

Jak opisać aplikację pod GitOps – minimalny zestaw

Zanim włączysz Argo CD, spójrz na swoje manifesty. Jaki masz cel? Chcesz szybkie POC czy od razu przygotować repozytorium na produkcję? Minimalny zestaw do sensownego GitOps dla typowej aplikacji webowej to zwykle:

  • Deployment – definicja pods, kontenerów, zasobów, sond, zmiennych środowisk,
  • Service – ekspozycja aplikacji w klastrze,
  • Ingress lub odpowiednik (Gateway, VirtualService) – dostęp z zewnątrz,
  • ConfigMap/Secret – konfiguracja, hasła, klucze (secrets najlepiej szyfrowane),
  • opcjonalnie: HorizontalPodAutoscaler, NetworkPolicy, PodDisruptionBudget.

Do tego dochodzą zasady nazewnictwa i wersjonowania obrazów. W GitOps tag obrazu jest kluczowy – to on determinuje, jaka wersja aplikacji jest wdrożona. Zmiana tagu to sygnał do Argo CD: „wdrażamy nową wersję”.

Przykładowy prosty manifest aplikacji webowej

Przykład minimalnego Deploymentu z myślą o GitOps (bez pełnej produkcyjnej „otoczki”):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-web
  labels:
    app: hello-web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello-web
  template:
    metadata:
      labels:
        app: hello-web
    spec:
      containers:
        - name: hello-web
          image: registry.example.com/hello-web:1.0.0
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /healthz
              port: 8080
          livenessProbe:
            httpGet:
              path: /live
              port: 8080

W kontekście GitOps najważniejsze tutaj są:

  • image – tag wersji, który zmieniasz w commitach,
  • labels – spójność etykiet ułatwia selektory i porządkuje zasoby,
  • probes – Argo CD dba o docelowy stan, ale bez poprawnych sond rollout będzie mniej przewidywalny.

Gdzie trzymasz swoje manifesty dziś?

Pytanie kontrolne: czy Twoje aktualne manifesty są w jednym repozytorium Git, czy rozsiane po różnych miejscach? Jeśli masz pliki na dyskach lokalnych, w wiki, w kilku repo, a część generuje osobny zespół – zacznij od inwentaryzacji. Argo CD wymaga, żeby to, co ma się znaleźć w klastrze, dało się odczytać z konkretnych ścieżek w konkretnych repozytoriach. Chaos w źródłach wejściowych przekłada się na chaos w GitOps.

Szczegółowy widok przemysłowych rur w saudyjskiej fabryce
Źródło: Pexels | Autor: Mumtaz Niazi

Architektura Argo CD – z czego składa się system i jak działa

Główne komponenty Argo CD

Argo CD składa się z kilku usług działających w klastrze Kubernetes. Znajomość ich roli bardzo pomaga w diagnozowaniu problemów i planowaniu zasobów.

  • API server – centralny komponent wystawiający API i UI:
    • obsługuje logowanie i uwierzytelnianie (lokalne, SSO, OAuth, OIDC),
    • komunikuje się z resztą komponentów,
    • przetwarza komendy użytkowników (sync, rollback, diff).
  • repo-server – serwer odpowiedzialny za interakcję z repozytoriami:
    • klonuje repozytoria Git,
    • renderuje aplikacje Helm/Kustomize,
    • przygotowuje manifesty do porównania i wdrożenia.
  • application-controller – „mózg” synchronizacji:
    • monitoruje Application CRD,
    • porównuje desired vs actual state,
    • inicjuje operacje wdrożeniowe zgodnie z politykami sync.
  • UI (argocd-server UI) – panel webowy:
    • wizualizacja stanu aplikacji i klastrów,
    • interaktywne diffy i logi,
    • szybkie operacje (sync, rollback, restart).

Przepływ zdarzeń: od commita w Git do zmian w klastrze

Wyobraź sobie, że zmieniasz tag obrazu w pliku Deploymentu i robisz commit. Co dalej?

  1. Commit w Git – zmiana trafia na branch, który jest skonfigurowany jako targetRevision w Application.
  2. Argo CD wykrywa różnicę – poprzez okresowe sprawdzanie repo lub webhook.
  3. repo-server pobiera repo – ściąga najnowszy stan, renderuje manifesty (Helm/Kustomize, jeśli używane).
  4. application-controller porównuje stan – sprawdza, czym różni się desired state od stanu klastra.
  5. Sync:
    • jeśli sync policy = manual – widzisz aplikację jako „OutOfSync” i decydujesz o synchronizacji,
    • jeśli sync policy = automated – controller sam podejmie akcję wdrożenia.
  6. Kubernetes wykonuje rollout – Argo CD wysyła zestaw manifestów do API serwera, resztą zajmują się kontrolery Kubernetesa.

Multi-cluster, multi-tenant – jak Argo CD skaluje się poza jeden klaster

Kiedy pierwszy klaster z Argo CD działa stabilnie, pojawia się kolejne pytanie: czy trzymasz wszystko w jednym klastrze, czy zarządzasz kilkoma środowiskami? Stage w jednym regionie, produkcja w innym, osobne klastry dla klientów? Argo CD dobrze wpisuje się w scenariusze, w których jeden „centralny” Argo CD steruje wieloma klastrami.

Podstawowy wzorzec to klaster zarządzający (management), w którym działa Argo CD, i klastry zarządzane (target), do których Argo CD ma dostęp. Dodając klaster zewnętrzny przez argocd cluster add, tworzysz w nim ServiceAccount i RoleBinding, które dają Argo CD odpowiednie uprawnienia. Od tej chwili w definicji Application możesz wskazywać destination.server jako konkretny klaster.

Jak daleko chcesz pójść z separacją? Dla wielu zespołów wygodny jest schemat:

  • jeden Argo CD dla środowisk nieprodukcyjnych (dev, stage, demo),
  • oddzielny Argo CD dla produkcji, często z ostrzejszymi zasadami dostępu i audytem,
  • czasem osobny Argo CD dla „klastrów klientów”, jeśli masz model SaaS z izolacją na poziomie klastra.

W multi-tenant ważne jest, by przemyśleć RBAC Argo CD i Namespace’y. Czy każdy zespół ma osobne projekty Argo CD (AppProject) i przestrzenie nazw? Czy może dzielicie namespace, ale ograniczacie dostęp po etykietach i nazwach aplikacji? Spróbuj odpowiedzieć sobie: jak chcesz odseparować uprawnienia między zespołami – po klastrze, po projekcie, po namespace?

AppProject – granice i polityki w Argo CD

AppProject to często pomijany, a bardzo ważny byt w Argo CD. Ty decydujesz, czy każdy zespół ma własny projekt, czy w jednym projekcie ląduje kilkanaście aplikacji. AppProject pozwala określić:

  • jakie repozytoria Git są dozwolone – np. tylko git@github.com:org/prod-gitops.git,
  • jakie klastry i namespace’y mogą być celem – np. tylko klaster production, namespace payments-*,
  • jakie rodzaje zasobów są dozwolone – możesz zablokować tworzenie np. ClusterRole przez zespół aplikacyjny,
  • politykę synchronizacji i health checki – rozszerzenia, customowe reguły.

Przykładowy szkic AppProject w YAML może wyglądać tak:

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: payments
  namespace: argocd
spec:
  description: "Aplikacje zespolu Payments"
  sourceRepos:
    - git@github.com:org/payments-gitops.git
  destinations:
    - server: https://kubernetes.default.svc
      namespace: payments-*
  clusterResourceWhitelist:
    - group: ""
      kind: Namespace
  namespaceResourceBlacklist:
    - group: rbac.authorization.k8s.io
      kind: RoleBinding

Widzisz tu kilka mechanizmów kontroli, ale kluczowe pytanie brzmi: które zasoby chcesz zostawić wyłącznie zespołowi platformowemu, a które oddać w ręce zespołów produktowych? AppProject pomaga to technicznie wyegzekwować.

Instalacja Argo CD na Kubernetesie krok po kroku

Wymagania wstępne – klaster i narzędzia

Zanim przejdziesz do instalacji, zatrzymaj się na chwilę i sprawdź: jakim klastrem dysponujesz? Lokalny kind, managed (EKS/GKE/AKS), a może on-premise?

Przyda się:

  • klaster Kubernetes w wersji co najmniej 1.22 (lepiej nowszy),
  • kubectl skonfigurowany do łączenia z klastrem,
  • opcjonalnie: argocd CLI – wygodne do zarządzania,
  • repozytorium Git, do którego masz dostęp do zapisu.

Zastanów się też, czy klaster ma dostęp do Internetu (pobieranie obrazów), czy korzystasz z prywatnego registry i czy potrzebne będą ImagePullSecrets.

Instalacja za pomocą manifestów YAML

Najprostsza ścieżka na start to instalacja z manifestu install.yaml dostarczanego przez projekt Argo CD. To dobry wariant, jeśli chcesz po prostu zobaczyć, jak narzędzie działa i nie zależy Ci jeszcze na finezyjnej konfiguracji Helm.

Podstawowe kroki:

  1. Utwórz namespace:
    kubectl create namespace argocd
    
  2. Zaaplikuj manifest:
    kubectl apply -n argocd 
      -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
    
  3. Sprawdź zasoby:
    kubectl get pods -n argocd
    

Jeśli potrzebujesz większej kontroli nad wersją, możesz wskazać konkretny tag w URL albo skopiować manifest do własnego repo i traktować go… deklaratywnie, również przez GitOps.

Ekspozycja panelu Argo CD

Domyślnie serwer Argo CD (argocd-server) jest wystawiony jako ClusterIP. Musisz zdecydować: czy chcesz mieć dostęp tylko z wewnątrz klastra, czy także z zewnątrz (VPN/Internet)?

Najprostsze opcje dla środowiska deweloperskiego:

  • port-forward:
    kubectl port-forward svc/argocd-server -n argocd 8080:443
    

    Po tym zabiegu UI jest dostępne pod https://localhost:8080.

  • zmiana serwisu na LoadBalancer (na odpowiednich klastrach):
    kubectl patch svc argocd-server -n argocd 
      -p '{"spec": {"type": "LoadBalancer"}}'
    
  • Ingress – jeśli masz kontroler Ingress (np. NGINX, Traefik) i DNS:
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: argocd-ingress
      namespace: argocd
    spec:
      rules:
        - host: argocd.example.com
          http:
            paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: argocd-server
                    port:
                      number: 443
    

Dla produkcji zwykle wybierzesz Ingress z TLS i ewentualnym SSO. Pytanie dla Ciebie: czy z UI Argo CD mają korzystać tylko inżynierowie, czy także product ownerzy, QA? Od tego zależy, jak „wypuścisz” serwis na zewnątrz.

Pierwsze logowanie i zmiana hasła admina

Domyślny użytkownik to admin, a początkowe hasło w standardowej instalacji przechowywane jest w Secrecie w namespace argocd. Aby je odczytać:

kubectl -n argocd get secret argocd-initial-admin-secret 
  -o jsonpath="{.data.password}" | base64 -d && echo

Po wejściu na UI zaloguj się jako admin i od razu ustaw nowe hasło albo skonfiguruj SSO (np. OIDC z Keycloakiem, Azure AD, Google). Jaki masz model dostępu dzisiaj? Jeśli większość usług korzysta z centralnego IdP, sensownie jest od razu wpiąć Argo CD w tę samą tożsamość.

Instalacja Argo CD przy użyciu Helm

Jeśli na co dzień używasz Helm, prawdopodobnie wygodniejsze będzie wdrożenie Argo CD jako chartu. Pozwala to na:

  • łatwe nadawanie własnych wartości (resources, tolerations, affinity),
  • integrację z istniejącym pipeline CI/CD,
  • traktowanie samego Argo CD jako „aplikacji GitOpsowej”.

Przykładowy minimalny zestaw komend:

helm repo add argo https://argoproj.github.io/argo-helm
helm repo update

kubectl create namespace argocd

helm install argocd argo/argo-cd 
  --namespace argocd 
  --values values-argocd.yaml

W pliku values-argocd.yaml możesz od razu zdefiniować typ serwisu, zasoby, konfigurację RBAC, SSO. Zastanów się: co w Twoim środowisku jest „nietypowe” względem domyślnej instalacji? Tam celujesz z własnymi wartościami.

Rura przemysłowa odprowadzająca ścieki na pustynnym, wiejskim terenie
Źródło: Pexels | Autor: Orhan Akbaba

Pierwsza aplikacja w Argo CD – od repozytorium Git do działającej usługi

Przygotowanie repozytorium z manifestami

Zanim utworzysz pierwszą Application, potrzebujesz repozytorium z manifestami. Pytanie pomocnicze: czy chcesz na początek wrzucić do Git pojedynczy, prosty Deployment, czy od razu „prawdziwą” aplikację z kilkoma komponentami?

Bezpieczny scenariusz startowy:

  • tworzysz osobne repozytorium, np. sample-gitops,
  • w katalogu apps/hello-web/ umieszczasz:
    • deployment.yaml,
    • service.yaml,
    • opcjonalnie ingress.yaml.

Struktura może wyglądać tak:

sample-gitops/
  apps/
    hello-web/
      deployment.yaml
      service.yaml
      ingress.yaml

Na początek nie komplikuj. Najpierw upewnij się, że Argo CD poprawnie zaczytuje pliki i wdraża aplikację, dopiero później dołóż np. Kustomize czy Helm.

Tworzenie Application – UI vs YAML

Możesz podejść do tematu dwojako. Co wolisz na start: klikać w UI, czy od razu pisać deklaratywny YAML i wrzucać go do Git?

Wariant 1: przez UI

  1. Wejdź do UI Argo CD i wybierz „NEW APP”.
  2. Ustaw nazwę aplikacji, np. hello-web.
  3. Wybierz projekt (na początek może być default).
  4. W sekcji „SOURCE”:
    • podaj URL re