Dlaczego webhooki GitHub przekraczają czas wobec Jenkinsa za VPN
GitHub wysyła webhooki do wewnątrz, więc VPN chroniący Jenkinsa je odrzuca. Przekaż dostawę na zewnątrz przez relay lub zastąp webhook agentem, który odpytuje.
Strona dostawy pokazuje przekroczenie czasu, a Jenkins nic nie rejestruje, co jest sygnaturą połączenia, które nigdy nie dotarło. GitHub wysyła webhook jako wychodzący HTTP POST z własnej infrastruktury na skonfigurowany payload URL. VPN chroni Jenkinsa, odrzucając dokładnie taki rodzaj połączenia. Po żadnej stronie nic nie jest zepsute. Problemem jest kierunek żądania.
Czego dostawa faktycznie próbuje
GitHub rozwiązuje nazwę hosta w payload URL i łączy się z nią z publicznego internetu. Jeśli ten URL wskazuje na adres prywatny lub na nazwę, która rozwiązuje się tylko w Twojej sieci, próba kończy się niepowodzeniem, zanim zostanie wysłane jakiekolwiek żądanie. Jeśli wskazuje na publiczną nazwę, którą odrzuca Twoja krawędź, próba zamiast tego przekracza czas.
Ta różnica ma znaczenie dla diagnozy. Awaria DNS i filtrowany port wyglądają tak, jakby po stronie Jenkinsa nic się nie stało, i oba pojawiają się w GitHubie jako nieudana dostawa z innym dołączonym powodem. Przeczytaj ten powód, zanim zmienisz URL.
Tunel, który wybiera połączenie na zewnątrz, nie tworzy nasłuchu. Właśnie tej części ludzie oczekują, że będzie działać inaczej.
Trzy sposoby naprawienia kierunku połączenia
Każde rozwiązanie zmienia to, kto inicjuje połączenie, i istnieją tylko trzy kształty.
| Approach | Who initiates | What you give up |
|---|---|---|
| Relay service | An outbound client inside the network | A third party sees every payload |
| Reverse tunnel or ingress | The public edge, into a controlled listener | An inbound surface you must secure |
| Runner or polling | The agent, outbound to GitHub | Instant delivery, replaced by a schedule |
Odpytowanie jest najmniej eleganckie i najłatwiejsze w utrzymaniu. Relay utrzymuje niemal natychmiastową informację zwrotną bez otwierania portu. Runner jest zwykle właściwą odpowiedzią, gdy poufność payloadu wyklucza stronę trzecią, ponieważ zadanie może działać na maszynie, która już znajduje się w sieci.
Wybieraj według tego, czym potrafisz zarządzać, a nie według tego, co brzmi nowocześnie.
Przekaż dostawę na zewnątrz za pomocą smee
Utwórz kanał w usłudze relay i zachowaj jego URL. W sieci zainstaluj klienta i przekazuj dostawy na ścieżkę, której oczekuje Jenkins. Payload URL w ustawieniach repozytorium staje się URL-em kanału, a typ treści jest ustawiony na application/json.
sudo npm install --global smee-client
smee -u CHANNEL_URL --path /github-webhook/ --port 8080Trzy szczegóły decydują, czy to zadziała. Ścieżka musi odpowiadać temu, czego Jenkins oczekuje dla zdarzeń GitHub, czyli domyślnie /github-webhook/. Jenkins musi nasłuchiwać na porcie, który dałeś klientowi. A skonfigurowany w zadaniu Jenkins URL musi zgadzać się z tą ścieżką, inaczej zdarzenie dotrze i zostanie odrzucone.
Niezgodność końcowego ukośnika daje 404, który czyta się jak nieudana dostawa, ale nią nie jest.
Uruchamianie tak, aby przetrwało tydzień
Klient na pierwszym planie umiera wraz z terminalem, a webhooki działają dzień, po czym się zatrzymują. Daj mu unit z Restart=always, uruchom jako użytkownik Jenkins i przeczytaj journal po pierwszej rzeczywistej dostawie. Właśnie ten ostatni krok odróżnia działający relay od skonfigurowanego.
[Unit]
Description=smee webhook relay
After=network.target
[Service]
Type=simple
Restart=always
RestartSec=2
User=jenkins
ExecStart=/usr/bin/smee -u CHANNEL_URL --path /github-webhook/ --port 8080
[Install]
WantedBy=multi-user.targetTestuj prawdziwym push, a nie przyciskiem odtwarzania. Odtwarzanie ćwiczy zapisany payload relay, a nie ścieżkę z GitHuba do Twojego kanału, więc może przejść, podczas gdy dostawa na żywo nadal zawodzi.
Alarmuj, gdy unit się zatrzyma. Relay, który leży, jest cichy z konstrukcji, a cisza jest dokładnie tym, co już debugujesz.
Co relay może zobaczyć i kiedy go nie używać
Relay kończy payload, więc widzi nazwy repozytoriów, dane commitów i wszystko inne, co niesie zdarzenie. Traktuj URL kanału jako publiczny punkt końcowy. Utrzymuj skonfigurowany tajny token Jenkinsa, aby fałszywe dostawy były odrzucane, i ogranicz token używany przez Jenkinsa do niezbędnego minimum.
Jeśli poufność payloadu to wyklucza, hostowany samodzielnie runner lub uwierzytelniony tunel odwrotny jest odpowiedzią.
Relay jest teraz infrastrukturą i zasługuje na taki sam przegląd jak build, który uruchamia. Obróć kanał, jeśli wycieknie, i zapisz datę ostatniego zweryfikowania dostawy na żywo. Umieść tę datę w runbooku obok URL-a kanału. Relay, którego nikt nie przejrzał przez rok, to publiczny punkt końcowy, którego nikt nie posiada.