Vaš korak za deploy visi na internom imenu hosta, dok ista naredba odgovara odmah s vašeg laptopa, a build klijenta na oba računara je identičan. Job se izvršava na GitHub-hostovanom runneru: virtuelnoj mašini napravljenoj za taj jedan job unutar GitHubovog oblaka, bez rute u vaš privatni adresni prostor, bez resolver zapisa za internu zonu i bez certifikata koji bi privatni endpoint prihvatio. Samo dva dizajna se uklapaju u to ograničenje, i nijedan se ne može uključiti kasnije bez ponovne izgradnje workflowa. Odaberite između njih prije prve linije YAML-a, jer migracija naknadno košta više od prvog pokušaja.

Izbor je između runnera postavljenog tamo gdje mreža već prestaje i tunela koji postoji za vrijeme trajanja jednog joba. Oba godinama nose produkcijske deploye, i padaju na različite načine.

Gdje granica zapravo leži

Sve što instalirate na laptop zaustavlja se na laptopu, a sve što instalirate tokom joba nestaje s runnerom. Ne postoji trajni mrežni namespace za koji bi klijent ostao vezan između pokretanja, pa svako pokretanje počinje u istom nedostižnom stanju. Azure dokumentuje tu granicu za agente koje hostuje Microsoft, gdje VPN i ExpressRoute veze u privatne mreže nisu podržane, a GitHub-hostovani runneri nose isti oblik ograničenja umjesto zasebnog mehanizma. Čitajte to kao osobinu proizvoda, ne kao defekt koji treba obilaziti.

Nijedna postavka repozitorija to ne ublažava. Oznaka joba odlučuje koji pool preuzima posao, a hostovana oznaka znači mašinu izvan vašeg perimetra za cijelo pokretanje.

Privatna dostupnost zato mora doći iz nečega što posjedujete. Runner postavljen tamo gdje mreža već prestaje, ili tunel koji živi jedan job. Ostatak članka govori o tome da svjesno platite jedno od toga umjesto da račun otkrijete u produkciji.

Odlučujte po frekvenciji pokretanja, ne po poznatosti

Posegnite za vlastitim runnerom u VPC-u ili kancelarijskoj mreži kada deployi stižu nekoliko puta dnevno, kada job dira više od jednog privatnog porta, ili kada tim za platformu već vodi patching i rotaciju akreditiva. Job na toj mašini resolva i rutira kao bilo koji drugi host iza firewall-a. Mrežni posao se dešava jednom, pri instalaciji, umjesto pri svakom pokretanju.

Napravite tunel unutar joba kada je pristup povremen i ne želite dugovječnog agenta koji drži akreditiv u vašu mrežu. Job postaje sopstveni mrežni klijent na nekoliko minuta i ne ostavlja ništa za sobom, što je često cijela poenta.

Procijenite cijenu tunela prije nego ga odaberete. Svako pokretanje plaća materijalizaciju profila, pokretanje klijenta, spremnost i demontažu. Tunel koji se podigne ali nikad ne verifikuje proizvodi deploy koji padne na pola puta i ostavlja privatno stanje u obliku koji niko nije planirao. Ponovni pokušaj poslije toga rijetko je čist, a drugi neuspjeh se obično pripiše verziji klijenta.

Pisanje profila tako da korak ne može abortirati

Držite profile i akreditive izvan repozitorija i materijalizujte ih iz secreta u koraku kojem trebaju. Redoslijed odlučuje da li job preživljava: fajl napravljen pod sudo pripada rootu, a neprivilegovani shell koraka onda ne može pisati u njega.

- name: Bring up OpenVPN
  run: |
    umask 077
    profile="$RUNNER_TEMP/client.ovpn"
    printf '%s\n' "$VPN_PROFILE" > "$profile"
    : > "$RUNNER_TEMP/openvpn.log"
    printf '%s\n' "$VPN_CREDENTIALS" > "$RUNNER_TEMP/credentials.txt"
    sudo openvpn --daemon openvpn-job \
      --config "$profile" \
      --auth-user-pass "$RUNNER_TEMP/credentials.txt" \
      --writepid "$RUNNER_TEMP/openvpn.pid" \
      --log "$RUNNER_TEMP/openvpn.log"

Oba detalja u tom bloku postoje za kasnije korake. Sa umask 077 profil stiže u modusu 0600 i vlasništvu korisnika runnera, sudo ga još može čitati, a klijent piše svoj log u fajl koji runner već posjeduje, pa spremnosna petlja može čitati taj log bez drugog sudo. --writepid bilježi PID na koji će demontaža ciljati.

Profil koji se autentifikuje klijentskim certifikatom treba svoj ključ zapisan na isti način, a profil sa statičkim izazovom treba odgovarajući auth mod. Profili koji guraju DNS opcije trebaju openvpn-systemd-resolved na Ubuntu i Debianu, jer samo guranje ništa ne mijenja na osnovnoj slici.

Spremnost je sonda, ne pauza

Fiksni sleep drži tačno do trenutka kada koncentrator postane spor, a tada korak deploya kreće prije nego ruta postoji. Neuspjeh se onda pojavi unutar deploy alata kao timeout prema privatnom hostu, što ništa ne govori o tunelu.

- name: Await private endpoint
  run: |
    for attempt in $(seq 1 30); do
      if getent hosts private.example.internal > /dev/null && \
         timeout 3 bash -c 'exec 3<>/dev/tcp/private.example.internal/8443' 2>/dev/null; then
        echo "endpoint answered after $attempt attempts"
        exit 0
      fi
      sleep 2
    done
    grep -Ei 'error|verify|auth' "$RUNNER_TEMP/openvpn.log" | tail -40
    exit 1

Petlja posmatra dvije stvari jer bilo koja od njih može biti pokvarena polovina. getent hosts dokazuje da gurnuti resolver odgovara za to ime, a otvaranje socketa dokazuje da nešto sluša na portu koji će deploy koristiti; profil samo s rutom treba doslovnu adresu i obrisanu liniju getent.

Kada petlja istekne, log je jedina stvar koja razdvaja tri različita kvara: odbijen certifikat, pogrešan auth mod i rutu koja nikad nije stigla. Filtriranje prije taila drži taj izlaz dovoljno kratkim za čitanje dok job još pada. Čitajte prvu grešku umjesto zadnje linije, jer klijent koji ne može da se autentifikuje ponavlja se dok petlja ne odustane. ip -4 route show dev tun0 odgovara na jednostavnije pitanje da li je ruta uopšte gurnuta, i košta jednu liniju unutar iste petlje.

Demontaža i pitanje artefakta

Zatvorite job korakom zaštićenim sa if: always() koji izvršava sudo kill "$(sudo cat "$RUNNER_TEMP/openvpn.pid")" i ništa drugo. Na dijeljenom vlastitom runneru nikada ne ubijajte po imenu procesa: drugi job može posjedovati klijenta s istim binarnim fajlom i sličnim argumentima. Neuspjeh onda padne na job koji je radio drugi, a njegov log pokazuje na workflow koji nije ništa pogriješio.

Zaštita je bitna jer neuspjeli deploy ipak ostavlja živ tunel. Bez always() korak čišćenja se preskače tačno kada je potreban, a sljedeće pokretanje kreće prema klijentu koji je već povezan.

Ostaje jedno pitanje prije nego usvojite bilo koji dizajn: da li build fazi uopšte treba privatna ruta? Deployment agent koji već sjedi u mreži može povući odobreni artefakt, što drži obične buildove dalje od privatne staze. Manje jobova koji drže tunel znači manje mjesta gdje se zastarjela ruta može sakriti.

Povezani članci