Teie deploy-samm jääb rippuma sisemisel hostnimel, samal ajal kui sama käsk vastab sülearvutist kohe ja kliendi build on mõlemas masinas identne. Job töötab GitHubi hostitud runneril: virtuaalmasin, mis loodi just selle ühe jobi jaoks GitHubi pilves, ilma marsruudita teie privaatsesse aadressiruumi, ilma resolver-kirjeta sisemise tsooni jaoks ja ilma sertifikaadita, mida privaatne endpoint aktsepteeriks. Selle piiranguga sobib ainult kaks kujundust ja kumbagi ei saa hiljem sisse lülitada workflow'd uuesti ehitamata. Valige nende vahel enne esimest YAML-rida, sest hiljem migreerimine maksab rohkem kui esimene katse.

Valik on runneri, mis paigutatakse sinna, kus võrk juba lõpeb, ja tunneli vahel, mis elab täpselt ühe jobi jooksul. Mõlemad on aastaid kandnud produktsiooni deploy'sid ja need ebaõnnestuvad erineval viisil.

Kus piir tegelikult asub

Kõik, mille sülearvutisse paigaldate, peatub sülearvutis, ja kõik, mille jobi ajal paigaldate, kaob koos runneriga. Pole püsivat võrgu-nimeruumi, mille külge klient käivituste vahel kinni jääks, seega algab iga käivitus samast kättesaamatust olekust. Azure dokumenteerib selle piiri Microsofti hostitud agentide puhul, kus VPN- ja ExpressRoute-ühendused privaatvõrkudesse ei ole toetatud, ja GitHubi hostitud runnerid kannavad sama kujuga piirangut, mitte eraldi mehhanismi. Lugege seda toote omadusena, mitte defektina, mida tuleks mööda minna.

Ükski hoidla seade ei lõdvesta seda. Jobi silt otsustab, milline pool töö võtab, ja hostitud silt tähendab masinat väljaspool teie perimeetrit kogu käivituse jooksul.

Seega peab privaatne kättesaadavus tulema millestki, mis kuulub teile. Runner, mis on paigutatud sinna, kus võrk juba lõpeb, või tunnel, mis elab ühe jobi. Ülejäänud artikkel räägib nende kahe eest teadlikult maksmisest, selle asemel et arve produktsioonis avastada.

Otsustage käivituste sageduse järgi, mitte harjumuse järgi

Kasutage oma runnerit VPC või kontorivõrgu sees, kui deploy'sid tuleb mitu korda päevas, kui job puudutab rohkem kui ühte privaatset porti või kui platvormimeeskond juba haldab paiku ja mandaatide rotatsiooni. Selle masina job lahendab ja marsruudib nagu iga teine host tulemüüri taga. Võrgutöö tehakse üks kord paigaldamise ajal, mitte igal käivitusel.

Ehitage tunnel jobi sees, kui juurdepääs on juhuslik ja te ei taha pika elueaga agenti, mis hoiab mandaati teie võrku. Jobist saab mõneks minutiks oma võrguklient ja see ei jäta midagi maha, mis on sageli kogu mõte.

Hinnake tunneli maksumust enne selle valimist. Iga käivitus maksab profiili loomise, kliendi käivitamise, valmisoleku ja lammutamise eest. Tunnel, mis tõuseb, kuid mida ei kontrollita kunagi, tekitab deploy, mis ebaõnnestub poolel teel ja jätab privaatse oleku kujule, mida keegi ei planeerinud. Järgnev korduskatse on harva puhas ja teine ebaõnnestumine pannakse tavaliselt kliendi versiooni süüks.

Profiili kirjutamine nii, et samm ei saaks katkeda

Hoidke profiilid ja mandaadid hoidlast väljas ning materialiseerige need secret'idest selles sammus, kus neid vaja on. Järjekord otsustab, kas job jääb ellu: sudo all loodud fail kuulub rootile ja sammu õigusteta shell ei saa sinna enam kirjutada.

- 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"

Selle ploki mõlemad detailid on mõeldud järgmisteks sammudeks. umask 077 korral maandub profiil režiimis 0600 runneri kasutaja omandisse, sudo saab seda ikka lugeda ja klient kirjutab logi faili, mis runneril juba on, nii et valmisoleku tsükkel saab seda logi lugeda ilma teise sudota. --writepid registreerib PIDi, millele lammutamine sihib.

Kliendisertifikaadiga autentiv profiil vajab oma võtit samamoodi kirjutatuna ja static-challenge profiil vajab vastavat auth-režiimi. DNS-valikuid pushivad profiilid vajavad Ubuntus ja Debianis openvpn-systemd-resolved, sest push üksi ei muuda baasimages midagi.

Valmisolek on sond, mitte paus

Fikseeritud sleep peab vastu täpselt hetkeni, mil kontsentraator aeglustub, ja siis jookseb deploy-samm enne, kui marsruut on olemas. Viga tuleb seejärel deploy-tööriista sees esile timeoutina privaatse hosti vastu, mis ei ütle tunneli kohta midagi.

- 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

Tsükkel jälgib kahte asja, sest kumbki võib olla katkine pool. getent hosts tõestab, et pushitud resolver vastab sellele nimele, ja socketi avanemine tõestab, et deploy kasutatavas portis kuulab keegi; ainult marsruudiga profiil vajab otsest aadressi ja getent rea kustutamist.

Kui tsükkel aegub, on logi ainus, mis eristab kolme erinevat riket: tagasi lükatud sertifikaat, vale auth-režiim ja marsruut, mis kunagi ei saabunud. Enne taili filtreerimine hoiab selle väljundi piisavalt lühikesena, et seda jobi veel ebaõnnestudes lugeda. Lugege esimest viga, mitte viimast rida, sest klient, mis ei suuda autentida, kordab end, kuni tsükkel annab alla. ip -4 route show dev tun0 vastab lihtsamale küsimusele, kas marsruut üldse pushiti, ja see maksab samas tsüklis ühe rea.

Lammutamine ja artefakti küsimus

Sulgege job sammuga, mida kaitseb if: always() ja mis käivitab sudo kill "$(sudo cat "$RUNNER_TEMP/openvpn.pid")" ega midagi muud. Jagatud omal runneril ärge kunagi tapke protsessi nime järgi: teisel jobil võib olla klient, millel on sama binaar ja sarnased argumendid. Viga langeb siis sellele jobile, mis jooksis teisena, ja selle logi osutab workflow'le, mis ei teinud midagi valesti.

Kaitse loeb, sest ebaõnnestunud deploy jätab ikkagi elusa tunneli. Ilma always() jäetakse puhastussamm vahele täpselt siis, kui seda vajatakse, ja järgmine käivitus algab juba ühendatud kliendi vastu.

Enne kummagi kujunduse omaksvõtmist jääb üks küsimus: kas build-ifaas vajab üldse privaatset marsruuti? Deployment-agent, mis juba istub võrgu sees, saab tõmmata kinnitatud artefakti ja see hoiab tavalised buildid privaatsest teest eemal. Vähem tunnelit hoidvaid jobe tähendab vähem kohti, kuhu aegunud marsruut saab peituda.

Seotud artiklid