VPN runnera CI: czy tunel przeżyje build?
Współdzielony runner CI zachowuje trasy i procesy między zadaniami. Zaplanuj stany VPN przed zadaniem, w jego trakcie i po nim, i sprzątaj tylko to połączenie, które należy do zadania.
Zadanie wdrożeniowe łączy się, kopiuje swój artefakt i zgłasza sukces. Tunel, który otworzyło, może nadal działać, gdy zaczyna się kolejne zadanie, a trasa, którą zmieniło, należy do całego hosta. Wynik builda opisuje polecenie, a nie stan, który po sobie zostawił. Traktuj VPN jak zasób z czasem życia, a nie jak jedną linię na początku etapu.
Co jeszcze działa na tym hoście
Węzeł Jenkinsa może uruchamiać kilka executorów naraz, a zadanie, które zmienia trasy hosta, ustawienia resolvera lub połączenie systemowe, zmienia je dla wszystkich. To, czy inny job to zauważy, zależy od polityki tras i filtrowania, a nie od ogólnej zasady dotyczącej VPN. Dostęp do repozytorium, dostęp do artefaktów i kanał sterowania to osobne wymagania, których runner nadal potrzebuje. Dodaj je do listy celów wdrożenia, zanim wybierzesz pełny tunel.
Jeśli kanał sterowania miałby przechodzić przez tunel, projekt musi to powiedzieć świadomie. Odkrycie tego podczas wycofywania nie jest planem. Zapisz dwie listy: do czego zadanie musi dotrzeć prywatnie i do czego runner musi dotrzeć niezależnie od wszystkiego.
Czy to zadanie w ogóle potrzebuje prywatnego dostępu?
Zapytaj przed dodaniem tunelu, czy etap builda go potrzebuje. Prywatny agent wdrożeniowy może pobrać zatwierdzony artefakt i wykonać wdrożenie, co trzyma ogólny etap builda poza siecią prywatną. Taki podział jest zwykle tańszy niż uczenie każdego kroku builda routingu przez tunel.
Wybieraj granicę z przepływu pracy, a nie z przyzwyczajenia. Jeśli odpowiedź brzmi nie, reszta tej strony jest zbędna, i to jest najlepszy dostępny wynik.
Stan, który dziedziczy kolejne zadanie
Opisz, co powinno być prawdą przed zadaniem, gdy ma prywatny dostęp, i po jego zakończeniu, łącznie z anulowaniem. Stan końcowy jest tym, który najczęściej pozostaje niewypowiedziany, i to jego dziedziczy kolejne zadanie. Zapisz go obok pipeline'u, zamiast zostawiać w czyjejś pamięci.
| Moment | What proves it | What leaks if it is skipped |
|---|---|---|
| Job start: pre-flight route check | The route table shows no tunnel from an earlier job, and the profile list is empty | A stale route sends deployment traffic into a dead tunnel |
| Job end: disconnect and shred | The profile is down and the temporary key file is gone | The next job inherits an open tunnel and a usable credential |
| Cancelled job: reboot or disposal | The host is replaced or rebooted before the next job starts | A killed process leaves the tunnel up with no owner |
Dedykowany lub jednorazowy agent ułatwia egzekwowanie tych granic. Kontener lub przestrzeń nazw pomaga tylko wtedy, gdy jego układ sieci i uprawnień naprawdę izoluje zmianę.
Zatrzymaj połączenie, nie program
Użyj ścieżki finalizacji pipeline'u, aby zamknąć połączenie rozpoczęte przez to zadanie i usunąć jego tymczasowe dane logowania. Nie dopasowuj procesów po nazwie programu na hoście, którego używają inne zadania; zatrzymaj raczej konkretne połączenie. Dwa polecenia poniżej to całe sprzątanie i żadne z nich nie zależy od znalezienia procesu.
vpn-cli disconnect --profile "$PROFILE"
rm -f "$RUNNER_TEMP/client.key"
Finalizacja nie jest izolacją: runner, który umiera, zachowuje otwarty tunel, a proces zatrzymany siłą całkowicie pomija blok. Dlatego samo polecenie sprzątania nie może być całym projektem. Oto jak to zawodzi w praktyce: zadanie wdrożeniowe zostaje anulowane na kroku kopiowania, blok finalizacji nigdy się nie uruchamia, a kolejne zadanie na tym samym hoście startuje z żywym tunelem i trasą wskazującą sieć, do której nie może dotrzeć. Awaria wygląda jak problem z 'DNS' w kolejnym buildzie, godziny po zakończeniu zadania, które ją spowodowało.
Zapisuj nazwę profilu i ścieżkę danych logowania w wyjściu zadania. Gołe polecenie rozłączenia bez identyfikatora jest trudne do audytu później. Linia logu jest też tym, co dowodzi, że blok się wykonał, gdy późniejsze śledztwo o to zapyta.
Daj zadaniu hosta, którego nikt inny nie używa
Jednorazowa infrastruktura usuwa problem dziedziczenia, zamiast nim zarządzać. Świeży agent dla każdego zadania startuje bez trasy, bez profilu i bez cudzych danych logowania, a jego zniszczenie sprząta to, co zadanie zostawiło. To kosztuje więcej na build i jest uczciwą ceną granicy, która nie zależy od kodu sprzątającego. Dla zadań dotykających sieci produkcyjnych to zwykle tańsza opcja, gdy policzy się incydenty.
Tam, gdzie współdzielony runner musi zostać, testuj awarię i anulowanie tak samo starannie jak udane kopiowanie. Test powinien pokazać, co zobaczyłoby kolejne zadanie, gdyby to zostało anulowane w połowie. Zadanie jest skończone, gdy jego dostęp i stan tymczasowy się zakończyły, a nie gdy polecenie kopiowania zwraca zero.