Blog JSystems - uwalniamy wiedzę!

Szukaj
Panel Proxmox w ciemnym motywie z kontenerem ai-devops-demo postawionym przez agenta AI przez Terraform, status running, tagi i wykres CPU
Kontener ai-devops-demo na klastrze Proxmox. Nie postawił go człowiek klikając w panelu - opisał go agent AI w Terraformie, a my wpisaliśmy jedno zdanie. Log zadań na dole to realny ślad operacji: Create, Start.

Codzienność DevOps-a to w dużej mierze powtarzalność: postaw maszynę, skonfiguruj sieć, wgraj pakiety, sprawdź, czy działa, a potem zrób to samo dwadzieścia razy. Zwykle klikamy w panelu albo piszemy skrypty, które z czasem rozjeżdżają się z rzeczywistością. W 2026 roku doszła trzecia droga: opisujemy cel w języku naturalnym, a agent AI tłumaczy go na realne operacje na infrastrukturze.

W tym artykule pokażemy to od początku do końca na żywej infrastrukturze. Podłączymy agenta do klastra Proxmox z ograniczonymi uprawnieniami, każemy mu wygenerować kod Terraform i postawić prawdziwy kontener, zobaczymy, jak radzi sobie z własnym błędem, jak wykrywa ręczne zmiany poza kodem, jak przepycha zmianę przez Pull Request z potokiem CI, zarządza flotą i skanuje wynik pod kątem podatności. Każdy zrzut poniżej pochodzi z realnego uruchomienia na naszym klastrze. To praktyczne wprowadzenie do tego, czego uczymy na szkoleniu AI dla DevOpsów. Jeśli dopiero zaczynasz, zajrzyj najpierw do przewodnika czym właściwie jest DevOps.

Agent AI w DevOps: to nie jest kolejny skrypt

Zacznijmy od pojęcia, które bywa nadużywane. Agent AI to nie chatbot podpowiadający komendy ani skrypt z zakodowanymi na sztywno krokami. To program oparty na dużym modelu językowym, który dostaje cel w języku naturalnym, sam rozkłada go na kroki, wywołuje realne narzędzia i - co najważniejsze - czyta wynik każdego kroku i decyduje, co dalej. Gdy komenda zwróci błąd, agent to widzi i próbuje inaczej, zamiast ślepo lecieć do końca.

Animacja pętli agenta AI: cel, plan, działanie przez narzędzie MCP, obserwacja wyniku i powrót do planowania przy błędzie
Pętla agenta. Po każdym kroku agent sprawdza realny wynik i decyduje, czy cel osiągnięty, czy trzeba poprawić podejście.

Ta pętla to cała różnica. Zwykły skrypt w bashu wykonuje polecenia po kolei; gdy któreś się wywali, albo się zatrzymuje, albo brnie dalej z zepsutym stanem. Agent traktuje wynik jako informację zwrotną. Zobaczymy to później na żywym przykładzie: agent poprosi o storage, którego nie ma, dostanie błąd, sam sprawdzi listę dostępnych zasobów i poprawi konfigurację. Skrypt w tym miejscu po prostu by się wywrócił.

Porównanie dwóch podejść do infrastruktury: ręczne skrypty i klikanie kontra agent AI z Infrastructure as Code
Nie chodzi o zastąpienie inżyniera, tylko o zdjęcie z niego powtarzalnej pracy i przeniesienie stanu infrastruktury do kodu, który da się przejrzeć i cofnąć.

Warto od razu ustawić oczekiwania. Agent nie zwalnia z myślenia i nie zastępuje wiedzy o infrastrukturze. Jest raczej bardzo szybkim, cierpliwym juniorem, który zna składnię wszystkich narzędzi i nie męczy się powtarzaniem. Odpowiedzialność za to, co trafia na produkcję, dalej jest po naszej stronie - dlatego zaraz pokażemy, jak zamknąć agenta w bezpiecznych ramach: ograniczonych uprawnieniach, Pull Requestach i potoku CI. Jeśli samo pojęcie agenta jest dla Ciebie nowe, mamy osobny przewodnik po agentach AI.

Protokół MCP i skille: jak agent w ogóle dotyka infrastruktury

Model językowy sam z siebie potrafi tylko generować tekst. Żeby zrobił cokolwiek na Proxmoksie, ktoś musi dać mu narzędzia. Tu wchodzi MCP (Model Context Protocol), protokół, który w ustandaryzowany sposób łączy asystenta AI z zewnętrznymi narzędziami. Po stronie infrastruktury uruchamiamy serwer MCP, który wystawia konkretne funkcje - na przykład wylistuj maszyny, utwórz kontener, uruchom komendę - a agent woła je tak, jakby wywoływał funkcje w kodzie, zamiast klikać w panelu.

Architektura protokołu MCP: agent AI łączy się przez serwer MCP z narzędziami DevOps - Proxmox API, Terraform i Git
Serwer MCP jest tłumaczem między językiem naturalnym a narzędziami. Agent nie wie, jak kliknąć w panelu - wie, że ma funkcję, która tworzy kontener.

Drugie pojęcie to skille, czyli gotowe procedury wielokrotnego użytku. Raz opisana czynność, na przykład postaw kontener z Debianem, zainstaluj serwer WWW i sprawdź, czy odpowiada, staje się klockiem, który agent odtwarza na zawołanie. Budujemy w ten sposób własną bibliotekę powtarzalnych operacji - tak samo jak wcześniej budowaliśmy bibliotekę skryptów, tylko o poziom wyżej. W praktyce w roli agenta wystąpi asystent w rodzaju Claude Code, a serwer MCP dla Proxmoksa to niewielka usługa, która pod spodem woła zwykłe API Proxmoksa. Kluczowe jest to, że agent nie dostaje pełnego dostępu do klikania po omacku - dostaje wąski, nazwany zestaw operacji, które ktoś świadomie mu udostępnił.

Szybki start: podłącz agenta do swojego Proxmoksa

Teoria za nami - zróbmy to na Twoim własnym Proxmoksie. Całość sprowadza się do trzech rzeczy: ograniczonego tokenu (żeby agent nie dostał roota), małego serwera MCP (który tłumaczy API Proxmoksa na narzędzia dla agenta) i jednej komendy, która wpina ten serwer w Claude Code. Zajmuje to kilka minut, a od tego momentu rozmawiasz ze swoim klastrem po polsku.

Krok 1. Ograniczony token. Na węźle klastra, jako administrator, tworzymy rolę o wąskich uprawnieniach i wystawiamy dla niej token API. Do samego odczytu stanu wystarczą uprawnienia audytu; do stawiania maszyn dokładamy operacje na maszynach, dysku i sieci. Roota nie oddajemy agentowi ani na chwilę - do znaczenia poszczególnych uprawnień wracamy w sekcji o bezpiecznym podłączeniu.

Ograniczony token - jednorazowo, jako administrator
# Na wezle klastra, jako administrator (root) - jednorazowo:
pveum role add AiAgent -privs "VM.Audit Datastore.Audit VM.Allocate \
  VM.Config.CPU VM.Config.Memory VM.Config.Disk VM.Config.Network \
  VM.Config.Options VM.PowerMgmt Datastore.AllocateSpace SDN.Use"
pveum user add agent-ai@pve
pveum aclmod / -user agent-ai@pve -role AiAgent
pveum user token add agent-ai@pve terraform --privsep 0
# token jest pokazywany RAZ przy tworzeniu - zapisz go w bezpiecznym miejscu

Krok 2. Mały serwer MCP. To kilkadziesiąt linii w Pythonie. Serwer wystawia kilka narzędzi - tutaj wypisanie węzłów i podsumowanie klastra - a pod spodem woła zwykłe API Proxmoksa z naszym tokenem. Tyle wystarczy, żeby agent zaczął widzieć realny stan. Zapisujemy to jako proxmox_mcp/server.py:

proxmox_mcp/server.py - minimalny serwer MCP do Proxmoksa
import os, json, ssl, urllib.request     # tylko biblioteka standardowa - zero zaleznosci
from mcp.server.fastmcp import FastMCP    # FastMCP: gotowy szkielet serwera MCP

# Adres panelu i token czytamy ze zmiennych srodowiskowych - nie trzymamy ich w kodzie:
ENDPOINT = os.environ["PROXMOX_ENDPOINT"].rstrip("/")  # np. https://192.168.1.11:8006
TOKEN    = os.environ["PROXMOX_TOKEN"]                  # format: user@realm!tokenid=sekret

# Panel Proxmoksa ma certyfikat self-signed, wiec dla tego polaczenia wylaczamy weryfikacje TLS:
_ctx = ssl.create_default_context()
_ctx.check_hostname = False
_ctx.verify_mode = ssl.CERT_NONE

mcp = FastMCP("proxmox")                   # tworzymy serwer MCP o nazwie "proxmox"

def _api(path):
    # Jedno miejsce, ktore puka do API Proxmoksa - token doklejamy w naglowku Authorization:
    req = urllib.request.Request(ENDPOINT + "/api2/json" + path,
        headers={"Authorization": "PVEAPIToken=" + TOKEN})
    # Odpowiedz to JSON; wlasciwe dane siedza pod kluczem "data":
    return json.load(urllib.request.urlopen(req, context=_ctx))["data"]

@mcp.tool()                                # @mcp.tool() udostepnia funkcje agentowi jako narzedzie
def list_nodes() -> str:
    """Wypisuje wezly klastra Proxmox wraz ze statusem."""  # docstring - opis, ktory widzi agent
    # /nodes zwraca liste wezlow; skladamy z niej tekst "nazwa: status", linia po linii:
    return "\n".join(f"{n['node']}: {n['status']}" for n in _api("/nodes"))

@mcp.tool()
def cluster_summary() -> str:
    """Ile wezlow online, ile maszyn dziala, czy jest kworum."""
    nodes = _api("/nodes")                             # lista wezlow klastra
    vms   = _api("/cluster/resources?type=vm")         # lista maszyn i kontenerow
    online = sum(n["status"] == "online" for n in nodes)   # ile wezlow jest online
    run    = sum(v["status"] == "running" for v in vms)    # ile maszyn faktycznie dziala
    quorum = "tak" if online > len(nodes) // 2 else "nie"  # kworum = wiecej niz polowa wezlow online
    return f"Wezly {online}/{len(nodes)} online, dziala {run}/{len(vms)} maszyn, kworum: {quorum}"

if __name__ == "__main__":
    mcp.run()   # start na transporcie stdio - Claude Code rozmawia z serwerem przez stdin/stdout

Krok 3. Wepnij serwer w Claude Code. Jedna komenda rejestruje serwer i przekazuje mu adres panelu oraz token przez zmienne środowiskowe - token nie ląduje w żadnym pliku w repozytorium. Zaraz potem sprawdzamy, że Claude Code faktycznie się z nim łączy:

Wpięcie serwera MCP w Claude Code
claude mcp add proxmox \
  --env PROXMOX_ENDPOINT=https://192.168.1.11:8006 \
  --env PROXMOX_TOKEN='agent-ai@pve!terraform=********' \
  -- python proxmox_mcp/server.py
Terminal: komenda claude mcp add rejestruje serwer proxmox, a claude mcp list pokazuje status Connected
Po rejestracji claude mcp list potwierdza połączenie: proxmox - Connected. Agent ma teraz do dyspozycji narzędzia Twojego Proxmoksa.

Krok 4. Pierwsze zapytanie. Zgodnie z zasadą najpierw odczyt zaczynamy od pytania, które niczego nie zmienia. Prosimy agenta o raport - a on sam wybiera, które narzędzie MCP wywołać, czyta realny wynik i składa z niego odpowiedź po polsku:

Połącz się z klastrem Proxmox przez serwer MCP proxmox. Wypisz węzły z ich statusem i podsumuj, ile maszyn działa i czy klaster ma kworum.
Terminal: agent przez serwer MCP proxmox wywołuje narzędzia i zwraca raport - trzy z czterech węzłów online, proxmox4 wyłączony, dziewięć z dwudziestu ośmiu maszyn działa, klaster ma kworum
Agent sam wywołał narzędzia MCP, odczytał realny stan klastra i złożył raport: trzy węzły online, proxmox4 wyłączony, 9 z 28 maszyn działa, kworum zachowane.

To wszystko - agent jest podłączony do Twojego klastra i widzi jego realny stan. Reszta artykułu pokazuje, co da się na tym zbudować: od generowania kodu Terraform, przez samonaprawę po błędzie, aż po GitOps i skan bezpieczeństwa.

Krajobraz narzędzi: Terraform, Ansible i Pulumi

Zanim agent cokolwiek zrobi, warto wiedzieć, czym właściwie steruje. Agent nie wymyśla nowego narzędzia - wybiera i łączy te, które w DevOps znamy od lat. Cała rodzina nazywa się Infrastructure as Code (infrastruktura jako kod): zamiast klikać, opisujemy pożądany stan w plikach.

Porównanie narzędzi Infrastructure as Code: ręczne skrypty, Ansible, Terraform i Pulumi - model, stan, język i zastosowanie
Cztery podejścia do infrastruktury jako kodu. Agent najczęściej sięga po Terraform do stawiania zasobów i po komendy na flocie tam, gdzie klasycznie użylibyśmy Ansible.

Różnica, na którą warto zwrócić uwagę, to model deklaratywny kontra proceduralny. W podejściu proceduralnym opisujemy kroki: zainstaluj to, uruchom tamto. W deklaratywnym opisujemy stan docelowy, a narzędzie samo określa, co trzeba zrobić, żeby go osiągnąć. Terraform jest deklaratywny i to jego trzymamy się w tym artykule, bo agentowi łatwo generować opis stanu, a Terraform bierze na siebie brudną robotę policzenia różnic. W dalszej części zobaczysz, jak bardzo to upraszcza życie przy zmianach i przy wychwytywaniu ręcznych zmian poza kodem.

Bezpieczne podłączenie: token zamiast hasła roota

Najgorsze, co można zrobić, to dać agentowi hasło roota do klastra i pozwolić mu na wszystko. Rozsądny pierwszy krok jest odwrotny: tworzymy rolę o minimalnych uprawnieniach i wystawiamy agentowi token API, który pozwala tylko na to, co faktycznie potrzebne. W Proxmoksie robimy to komendą pveum. Poprosiliśmy agenta, żeby przygotował sobie taki ograniczony dostęp:

Podłącz się do Proxmoksa, ale nie używaj konta roota. Utwórz rolę z minimalnym zestawem uprawnień potrzebnym do zarządzania kontenerami (tworzenie, pamięć, dysk, sieć, zasilanie) i wygeneruj dla niej token API. Pokaż mi, jakie dokładnie uprawnienia dostał ten token.
Terminal: agent tworzy w Proxmoksie rolę o ograniczonych uprawnieniach oraz token API dla agenta, bez dostępu roota
Agent tworzy rolę AiAgent, użytkownika i token API. Na dole widać dokładny zakres uprawnień - są tam operacje na maszynach i storage, ale nie ma modyfikacji systemu, zarządzania użytkownikami ani kasowania klastra.

Skąd bierze się to pierwsze połączenie z Proxmoksem? Samo utworzenie roli i tokenu wymaga uprawnień administratora, więc ten jeden, wstępny krok wykonujemy my - jako administrator klastra, łącząc się z węzłem po SSH i uruchamiając polecenia pveum. To celowe: konto roota pojawia się tylko na chwilę, żeby wykuć ograniczony token. Od tej pory agent dostaje do ręki wyłącznie ten token i całą dalszą pracę - odczyt stanu, stawianie maszyn, zmiany, skany - wykonuje już bez hasła roota, przez serwer MCP i Terraform, które tym tokenem się uwierzytelniają.

To jest zasada najmniejszych uprawnień (least privilege) w praktyce. Gdyby token wyciekł albo agent zrobił coś nie tak, największa możliwa szkoda ogranicza się do maszyn wirtualnych - nie do całego węzła. Token pokazujemy tylko raz przy tworzeniu, dlatego od razu ląduje w bezpiecznym miejscu, nigdy w repozytorium. Ograniczony token to pierwsza z kilku warstw, którymi trzymamy agenta w ryzach:

Infografika pięciu warstw bezpieczeństwa przy pracy z agentem AI: token o minimalnych uprawnieniach, poświadczenia w zmiennych środowiskowych, Pull Request, potok CI i skan obrazów
Pięć niezależnych warstw. Żadna z nich nie jest skomplikowana, a razem sprawiają, że agent przyspiesza pracę, nie zwiększając ryzyka.

Pierwszy kontakt: agent czyta stan klastra

Druga zasada bezpiecznego wdrażania agenta brzmi: najpierw odczyt, potem zapis. Zanim pozwolimy agentowi cokolwiek tworzyć, dajemy mu operacje odczytu i prosimy o raport. To buduje zaufanie i od razu pokazuje, czy agent dobrze rozumie nasze środowisko. Poprosiliśmy o podsumowanie stanu klastra:

Pokaż węzły klastra Proxmox i ile maszyn na nich działa. Zaznacz, jeśli któryś węzeł jest niedostępny.
Terminal: agent AI odpytuje klaster Proxmox przez narzędzia MCP i zwraca tabelę węzłów oraz liczbę maszyn
Agent woła funkcje serwera MCP i składa z nich czytelny raport. Trzy węzły online, jeden wyłączony poza kworum, plus liczba kontenerów i maszyn.

Zwróć uwagę na ostatnie zdanie odpowiedzi. Agent nie tylko wypisał dane - zauważył, że węzeł proxmox4 jest wyłączony, i sam ocenił, że nie blokuje to operacji, bo klaster ma kworum (większość węzłów pozwalającą podejmować decyzje, tutaj trzy z czterech głosów). Ta warstwa interpretacji odróżnia agenta od surowego zapytania do API. Ten sam stan floty widać w panelu Proxmoksa:

Widok Datacenter Search w panelu Proxmox w ciemnym motywie pokazujący całą flotę kontenerów i maszyn na węzłach klastra
Widok floty w panelu. Agent operuje na dokładnie tych samych zasobach, tylko przez API zamiast przez kliknięcia. Na liście kontener z tagami ai-demo i terraform, który za chwilę postawimy.

Warsztat: z jednego zdania do działającej maszyny

Teraz sedno. Chcemy nową maszynę, ale nie postawimy jej ręcznie. Poprosimy agenta, żeby opisał ją w Terraformie - a Terraform sam doprowadzi klaster do tego stanu. Zwróć uwagę, jak konkretne jest polecenie: to nadal język naturalny, ale z parametrami, które mają znaczenie dla infrastruktury.

Animacja przepływu od polecenia w języku naturalnym przez agenta i Terraform aż do działającego kontenera na Proxmoksie
Droga od zdania do maszyny: polecenie, agent wybiera narzędzie, Terraform planuje i wdraża, na końcu kontener działa na klastrze.
Wygeneruj konfigurację Terraform, która utworzy kontener LXC na moim klastrze Proxmox. Debian 12, 1 rdzeń, 512 MB RAM, dysk 4 GB na storage nfs-storage, adres z DHCP. Hasła do Proxmoksa czytaj ze zmiennych środowiskowych, nie zapisuj ich w pliku. Oznacz kontener tagami ai-demo i terraform.

Agent zwrócił gotowy plik main.tf. Na górze deklarujemy providera - wtyczkę, która uczy Terraform rozmawiać z konkretną platformą, tutaj z Proxmoksem. Od razu widać dobrą praktykę: w konfiguracji providera nie ma żadnego hasła.

main.tf - provider Proxmox
terraform {
  required_version = ">= 1.6"
  required_providers {
    proxmox = {
      source  = "bpg/proxmox"
      version = "~> 0.66"
    }
  }
}

# Poswiadczenia czytane ze zmiennych srodowiskowych (PROXMOX_VE_*),
# nigdy nie trzymamy hasel w repozytorium.
provider "proxmox" {
  insecure = true
  ssh {
    agent = false
  }
}

Sam kontener opisujemy jako jeden zasób. To jest cała definicja maszyny - deklaratywna, czytelna, gotowa do trzymania w repozytorium:

main.tf - definicja kontenera
resource "proxmox_virtual_environment_container" "ai_demo" {
  node_name     = "proxmox1"
  vm_id         = 990
  description   = "Demo utworzone przez agenta AI przez Terraform"
  tags          = ["ai-demo", "terraform"]
  unprivileged  = true
  started       = true

  initialization {
    hostname = "ai-devops-demo"
    ip_config {
      ipv4 { address = "dhcp" }
    }
  }

  operating_system {
    template_file_id = "nfs-storage:vztmpl/debian-12-standard_12.12-1_amd64.tar.zst"
    type             = "debian"
  }

  cpu    { cores = 1 }
  memory { dedicated = 512 }
  disk   { datastore_id = "nfs-storage", size = 4 }
  network_interface { name = "eth0", bridge = "vmbr0" }
}

Poświadczenia przekazujemy przez zmienne środowiskowe. Dzięki temu hasło nie ląduje w pliku ani w historii Gita - provider bpg/proxmox sam czyta zmienne z prefiksem PROXMOX_VE_. Potem trzy komendy: init pobiera providera, plan pokazuje, co powstanie (nic jeszcze nie zmieniając), a apply wykonuje zmianę.

Trzy komendy Terraform
export PROXMOX_VE_ENDPOINT="https://192.168.1.11:8006/"
export PROXMOX_VE_USERNAME="agent-ai@pve!terraform"
export PROXMOX_VE_PASSWORD="********"

terraform init      # pobiera providera bpg/proxmox
terraform plan      # pokazuje, co powstanie - nic jeszcze nie zmienia
terraform apply     # dopiero teraz tworzy maszyne

Komenda plan jest tu cichym bohaterem. Terraform pokazuje dokładnie, co zamierza zrobić, zanim cokolwiek ruszy - to bezpieczna klamra, której brakuje ręcznym skryptom. Oto realny wynik z naszego klastra:

Terminal z wynikiem terraform apply: plan tworzący jeden zasób i komunikat Creation complete po 13 sekundach oraz Apply complete
Realny terraform apply na naszym klastrze. Kontener powstał w 13 sekund. Na dole Terraform zwraca zdefiniowane wcześniej wartości wyjściowe: nazwę i numer maszyny.

Trzynaście sekund od komendy do działającej maszyny. Gdyby agent uruchomił apply drugi raz bez zmian w pliku, Terraform nie zrobiłby nic - stwierdziłby, że rzeczywistość już zgadza się z opisem. Ta właściwość nazywa się idempotencją (wielokrotne wykonanie daje ten sam efekt co jednokrotne) i jest fundamentem spokojnego snu w DevOps.

Zmienne i pętle: kod, który skaluje się z jednej maszyny na flotę

Jeden kontener to demonstracja. Prawdziwa siła Infrastructure as Code pojawia się, gdy z tego samego opisu chcemy postawić dziesięć maszyn różniących się kilkoma parametrami. Zamiast kopiować blok dziesięć razy, wyciągamy zmienne i używamy pętli for_each. Poprosiliśmy agenta o refaktoryzację:

Przerób konfigurację tak, żeby flotę kontenerów opisywała jedna zmienna typu mapa. Każdy wpis to nazwa i parametry: numer, liczba rdzeni, pamięć. Użyj for_each, żeby nie powtarzać bloku dla każdej maszyny.
main.tf - flota z jednej definicji
variable "kontenery" {
  description = "Flota kontenerow: nazwa -> parametry"
  type = map(object({
    vm_id  = number
    cores  = number
    memory = number
  }))
  default = {
    "web-01" = { vm_id = 990, cores = 1, memory = 512 }
    "web-02" = { vm_id = 991, cores = 2, memory = 1024 }
    "web-03" = { vm_id = 992, cores = 2, memory = 2048 }
  }
}

resource "proxmox_virtual_environment_container" "flota" {
  for_each  = var.kontenery
  node_name = "proxmox1"
  vm_id     = each.value.vm_id

  cpu    { cores = each.value.cores }
  memory { dedicated = each.value.memory }
  # reszta definicji jak wczesniej: system, siec, dysk...
}

Teraz dodanie czwartej maszyny to dopisanie jednej linii do zmiennej. Terraform sam policzy, że trzeba dodać jeden kontener, a reszty nie ruszać. To jest ta różnica, o której mówiliśmy przy porównaniu narzędzi: opisujemy stan, nie kroki. Agent świetnie sobie radzi z takim refaktorem, bo to mechaniczna, powtarzalna zmiana - dokładnie ten rodzaj pracy, który najlepiej mu oddać.

Gdy agent się myli: samonaprawa po błędzie

Obiecaliśmy pokazać pętlę agenta w akcji. Oto ona. Celowo kazaliśmy agentowi użyć storage o nazwie fast-ssd, którego na naszym klastrze nie ma. Zwykły skrypt wywaliłby się i zostawił nas z błędem. Zobaczmy, co robi agent:

Postaw kontener err-demo na storage fast-ssd. Jeśli coś nie zadziała, sprawdź, co jest dostępne, i popraw konfigurację samodzielnie.
Terminal: terraform apply zwraca błąd, że storage fast-ssd nie istnieje, agent sprawdza dostępne zasoby i poprawia konfigurację, po czym kontener powstaje
Pętla agenta na żywo: błąd o nieistniejącym storage, sprawdzenie dostępnych zasobów komendą pvesm status, poprawa na nfs-storage i udany drugi przebieg.

To jest ta różnica między agentem a skryptem, sprowadzona do jednego zrzutu. Terraform zwrócił konkretny błąd z Proxmoksa: storage fast-ssd does not exist. Agent go przeczytał, wykonał pvesm status żeby zobaczyć, jakie storage są dostępne, wybrał nfs-storage, poprawił jedną linię w konfiguracji i uruchomił apply ponownie - tym razem z sukcesem. Nikt nie musiał interweniować. Właśnie po to jest pętla obserwuj i popraw z pierwszej sekcji.

Kiedy maszyna rozjeżdża się z kodem: dlaczego kod musi być źródłem prawdy

Jest jeszcze jeden problem, który Infrastructure as Code rozwiązuje po cichu, a który potrafi zatruć życie przy ręcznym zarządzaniu: stan maszyny rozjeżdża się z kodem (po angielsku nazywa się to configuration drift). Dzieje się, gdy ktoś zmieni coś na maszynie bezpośrednio, poza kodem - na przykład szybko podbije pamięć w panelu, żeby ugasić pożar, i zapomni to zapisać. Rzeczywistość rozjeżdża się z opisem. Zasymulowaliśmy to i poprosiliśmy agenta o sprawdzenie:

Ktoś zmienił pamięć kontenera ai-devops-demo ręcznie w panelu. Sprawdź, czy stan klastra nadal zgadza się z konfiguracją w repozytorium.
Terminal: po ręcznej zmianie pamięci terraform plan wykrywa różnicę i pokazuje dedicated 1024 na 512 między stanem realnym a kodem
Terraform wykrywa różnicę między kodem a maszyną. Ktoś ustawił pamięć na 1024 poza kodem, a repozytorium mówi 512. Plan pokazuje dokładnie tę różnicę i proponuje przywrócenie stanu z kodu.

Terraform po cichu odświeżył stan realny, porównał go z kodem i pokazał: Objects have changed outside of Terraform, a pamięć różni się o dokładnie tę wartość, którą ktoś zmienił ręcznie. Jedno terraform apply przywraca stan zapisany w repozytorium. To jest sedno podejścia: kod jest jedynym źródłem prawdy, a wszystko, co się od niego oddaliło, da się wykryć i cofnąć. Bez tego po pół roku nikt już nie wie, dlaczego dana maszyna wygląda tak, a nie inaczej.

Kontrola wersji i GitOps: nic nie wchodzi bez Pull Requesta

Skoro cała infrastruktura jest teraz kodem, traktujmy ją jak kod. Plik main.tf trafia do repozytorium Git i zaczynamy pracować w modelu GitOps: repozytorium jest jedynym źródłem prawdy o stanie infrastruktury, a każda zmiana wchodzi przez Pull Request (propozycję zmiany, którą ktoś przegląda i zatwierdza), nigdy przez ręczne dłubanie na serwerze.

Animacja przepływu GitOps: od polecenia w języku naturalnym, przez edycję kodu przez agenta, Pull Request, potok CI, merge, aż po terraform apply
Pętla GitOps. Zmiana przechodzi przez przegląd i automatyczny potok CI, zanim dotknie infrastruktury. Historia zmian, kto i kiedy, zostaje w commitach.

Do repozytorium dokładamy potok CI (Continuous Integration - automatyczne sprawdzanie kodu przy każdej zmianie). Na start nie musi wdrażać; wystarczy, że sprawdzi formatowanie i poprawność konfiguracji Terraform. Plik dla GitHub Actions opisujemy raz:

.github/workflows/ci.yml
name: IaC CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  terraform:
    name: Terraform fmt + validate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: 1.9.8
      - name: Sprawdzenie formatowania
        run: terraform -chdir=infra fmt -check -diff
      - name: Inicjalizacja (bez backendu)
        run: terraform -chdir=infra init -backend=false
      - name: Walidacja konfiguracji
        run: terraform -chdir=infra validate

Teraz scenariusz z życia. Chcemy zwiększyć pamięć kontenera. Nie edytujemy niczego ręcznie na serwerze - mówimy agentowi, czego chcemy, a on przygotowuje zmianę i otwiera Pull Request:

Zwiększ pamięć kontenera ai-devops-demo z 512 MB do 1 GB. Zmień tylko odpowiednie pole w infra/main.tf, utwórz osobną gałąź i otwórz Pull Request z krótkim opisem, co i po co zmieniasz.
Pull Request na GitHubie ze zmianą pamięci kontenera z 512 MB na 1 GB, z opisem wygenerowanym przez agenta i zielonym znacznikiem CI
Pull Request otwarty przez agenta. Zmiana czeka na przegląd i na potok CI. Nic nie dzieje się na klastrze, dopóki ktoś tego nie zatwierdzi i nie scali.

Po otwarciu Pull Requesta GitHub Actions automatycznie uruchomił nasz potok - sprawdził formatowanie, pobrał providera, zwalidował konfigurację, wszystko na zielono, zanim człowiek w ogóle spojrzał na zmianę:

Przebieg GitHub Actions z zielonymi krokami potoku Terraform: formatowanie, inicjalizacja i walidacja konfiguracji zakończone sukcesem
Potok CI po polsku, wszystkie kroki zielone w 8 sekund. Błąd w konfiguracji zatrzymałby zmianę tutaj, nie na produkcji.

Największa wartość GitOps ujawnia się, gdy coś pójdzie źle. Skoro stan infrastruktury to historia commitów, cofnięcie awaryjnej zmiany wygląda dokładnie jak cofnięcie błędu w kodzie aplikacji:

Cofnięcie zmiany w modelu GitOps
git revert HEAD      # tworzy commit odwracajacy ostatnia zmiane
git push             # potok CI rusza ponownie

# po scaleniu terraform apply przywraca poprzedni, dzialajacy stan

Zamiast gorączkowego klikania po panelu w środku nocy - jeden commit i infrastruktura wraca do znanego, działającego stanu. O wpinaniu asystenta AI w takie potoki napisaliśmy szerzej w artykule o automatyzacji potoku CI/CD z AI.

Agent zamiast Ansible: zarządzanie flotą w języku naturalnym

Stawianie maszyn to jedno, ale codzienność DevOps to też zarządzanie tym, co już działa: zbieranie informacji z wielu hostów, instalowanie pakietów, pilnowanie konfiguracji. Klasycznie robimy to Ansiblem albo skryptami po SSH. Agent potrafi wejść w tę rolę, a instrukcje dostaje po polsku:

Na kontenerach demo (990, 261, 271) zbierz wersję systemu i czas działania. Następnie na ai-devops-demo zainstaluj i uruchom nginx, a na koniec sprawdź, czy odpowiada na porcie 80.
Terminal: agent zbiera fakty z trzech kontenerów Proxmox, instaluje nginx na ai-devops-demo i potwierdza odpowiedź HTTP 200
Agent zebrał fakty z floty (odpowiednik ad-hoc Ansible), zainstalował serwer WWW na naszym kontenerze i sam zweryfikował, że odpowiada. Wersja nginx i kod HTTP 200 to realne wyjścia z maszyn.

Zwróć uwagę na ostatnią linię. Agent nie zakończył pracy na komunikacie zainstalowano - sam wykonał zapytanie HTTP i potwierdził, że serwer zwraca HTTP 200. To znowu ta sama pętla: działanie, obserwacja, weryfikacja celu. Ansible też by to zrobił, ale musielibyśmy najpierw napisać każdy krok. Tutaj opisaliśmy cel jednym zdaniem, a agent dobrał komendy i sprawdził efekt. Narzędzia nie idą do kosza - agent najczęściej korzysta z nich pod spodem. Zmienia się warstwa, na której pracujemy: z pisania każdej komendy na opisywanie celu i pilnowanie, żeby efekt był zgodny z zamiarem.

Bezpieczeństwo i monitoring: agent, który sam się pilnuje

Automatyzacja bez kontroli bezpieczeństwa to proszenie się o kłopoty. Dlatego do procesu dokładamy skanowanie. Nasz kontener dostał serwer nginx w wersji 1.22.1 - poprosiliśmy agenta, żeby sprawdził, czy obraz tej wersji nie ciągnie za sobą znanych podatności:

Przeskanuj obraz nginx:1.22.1, który wdrożyliśmy, pod kątem podatności o wadze HIGH i CRITICAL. Podsumuj liczbę problemów i zaproponuj, co z tym zrobić.
Terminal ze skanem bezpieczeństwa: narzędzie trivy znajduje 176 podatności w obrazie nginx 1.22.1, w tym 19 krytycznych
Skan obrazu nginx 1.22.1 narzędziem trivy. 176 podatności, w tym 19 krytycznych - bo obraz opiera się na starym Debianie 11.6. Agent od razu proponuje przypięcie nowszego obrazu i dodanie skanu do potoku CI.

To realny, niewygodny wynik: 176 podatności, z czego 19 krytycznych. Nie dlatego, że nginx jest zły, tylko dlatego, że przypięliśmy starą wersję opartą na przestarzałym systemie bazowym. Wartość agenta polega tu na tym, że nie zostawia nas z suchą listą - wskazuje przyczynę i proponuje konkretny następny krok: przypiąć nowszy obraz i wpiąć skan do potoku CI, żeby taki problem został wyłapany automatycznie przy kolejnej zmianie. To ta sama piąta warstwa, którą widzieliśmy na diagramie bezpieczeństwa. Podobne podejście do przeglądów kodu opisaliśmy w artykule o wyszukiwaniu podatności aplikacji webowej.

Uwaga o zaufaniu. Im więcej agent może zrobić, tym więcej może zepsuć. Dlatego trzymamy się warstw z tego artykułu: token o minimalnych uprawnieniach, poświadczenia w zmiennych środowiskowych, zmiany przez Pull Request i potok CI, skan przed wdrożeniem. Agent przyspiesza pracę, ale to my ustawiamy bariery.

Kiedy to się opłaca, a kiedy jeszcze nie

Uczciwie: agenci w DevOps nie są odpowiedzią na wszystko. Najwięcej dają tam, gdzie zadania są powtarzalne, dobrze opisane i mają jasny sposób weryfikacji - stawianie środowisk testowych, przygotowywanie kodu IaC, refaktory takie jak przejście na for_each, zbieranie informacji z floty, rutynowe przeglądy. W takich miejscach oszczędność czasu bywa liczona w kilku godzinach dziennie, bo znika przełączanie się między narzędziami i przepisywanie tych samych komend.

Ostrożniej podchodzimy tam, gdzie błąd jest kosztowny i trudny do cofnięcia: operacje na produkcyjnych bazach, zmiany sieci odcinające dostęp, akcje bez sensownego podglądu tego, co się stanie. Tam agent może przygotować propozycję, ale ostatnie słowo należy do człowieka. Zdrowy model to nie pełna autonomia, tylko agent jako bardzo sprawny asystent działający w ramach, które sami wyznaczamy - dokładnie tych, które budowaliśmy przez cały ten artykuł.

Od czego zacząć u siebie

Animacja pięciu kroków wdrażania agentów AI w DevOps: podłączenie agenta, odczyt, przeniesienie stanu do kodu, GitOps i bezpieczeństwo
Pięć kroków, które można przejść na własnej infrastrukturze. Każdy z nich pokazaliśmy wyżej na żywym przykładzie.

Nie trzeba zaczynać od produkcji ani od pełnej automatyzacji. Wystarczy jedno bezpieczne środowisko - może być darmowy Proxmox na starym komputerze albo lokalny Docker - podłączony agent z ograniczonym tokenem i jedno realne zadanie do przejścia od początku do końca. Gdy zobaczysz, że agent poprawnie czyta stan i generuje sensowny kod, kolejne warstwy - Terraform, Pull Requesty, skany - dokładasz stopniowo.

Podsumowanie

Przeszliśmy pełną drogę: od zdania w języku naturalnym, przez ograniczony token i protokół MCP, wygenerowany kod Terraform, realny kontener na klastrze Proxmox, refaktor na flotę, samonaprawę po błędzie, wykrycie ręcznych zmian poza kodem, Pull Request z potokiem CI, zarządzanie flotą aż po skan bezpieczeństwa. Wszystko na żywej infrastrukturze i z prawdziwymi wynikami, łącznie z tymi niewygodnymi. Najważniejszy wniosek nie brzmi agent zastąpi DevOps-a. Brzmi: agent przenosi nas o poziom wyżej - z ręcznego wykonywania komend do opisywania celów i pilnowania, żeby to, co ląduje na infrastrukturze, było świadome, przejrzane i odwracalne.

To szkolenie może być dofinansowane dla Ciebie z KFS lub BUR.

★★★★★Średnia ocena naszych szkoleń w Google: 5/5

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...