तपाईंको deploy चरण कुनै आन्तरिक hostname मा अड्किन्छ, जबकि त्यही कमाण्ड तपाईंको ल्यापटपबाट तुरुन्तै जवाफ दिन्छ, र दुवै मेसिनमा client build एउटै हुन्छ। job GitHub-होस्ट गरिएको runner मा चलिरहेको छ: त्यही एउटा job का लागि GitHub को क्लाउडभित्र बनाइएको भर्चुअल मेसिन, तपाईंको निजी ठेगाना ठाउँमा कुनै रुट छैन, आन्तरिक जोनका लागि resolver प्रविष्टि छैन र निजी endpoint ले स्वीकार्ने कुनै प्रमाणपत्र छैन। यो सीमाभित्र दुईवटा मात्र डिजाइन अट्छन्, र workflow पुनः नबनाई कुनै पनि पछि सक्रिय गर्न सकिँदैन। YAML को पहिलो हरफअघि नै छान्नुहोस्, किनकि पछि स्थानान्तरण पहिलो प्रयासभन्दा बढी महँगो पर्छ।

छनोट नेटवर्क पहिल्यै सकिने ठाउँमा राखिएको runner र एउटा job जति बाँच्ने टनेलबीचको हो। दुवैले वर्षौंदेखि production deploy बोकिरहेका छन्, र फरक तरिकाले असफल हुन्छन्।

सीमा वास्तवमा कहाँ छ

तपाईं ल्यापटपमा जे जति इन्स्टल गर्नुहुन्छ त्यो ल्यापटपमै रोकिन्छ, र job का क्रममा जे इन्स्टल गर्नुहुन्छ त्यो runner सँगै हराउँछ। client रनहरूबीच जोडिरहने कुनै स्थायी नेटवर्क namespace छैन, त्यसैले हरेक रन त्यही अगम्य अवस्थाबाट सुरु हुन्छ। Azure ले यो सीमा Microsoft-होस्ट गरिएका agents का लागि अभिलेख गर्छ, जहाँ निजी नेटवर्कमा VPN र ExpressRoute जडान समर्थित छैनन्, र GitHub-होस्ट गरिएका runners ले त्यही प्रकारको प्रतिबन्ध बोक्छन्, छुट्टै संयन्त्र होइन। यसलाई उत्पादनको गुणका रूपमा पढ्नुहोस्, बाइपास गर्नुपर्ने दोषका रूपमा होइन।

repository को कुनै सेटिङले यसलाई खुकुलो बनाउँदैन। job को लेबलले कुन pool ले काम लिन्छ भन्ने तय गर्छ, र होस्ट गरिएको लेबल भनेको सम्पूर्ण रनभरि तपाईंको परिधिबाहिरको मेसिन हो।

निजी पहुँच त्यसैले तपाईंको स्वामित्वको कुनै कुराबाट आउनुपर्छ। नेटवर्क पहिल्यै सकिने ठाउँमा राखिएको runner, वा एउटा job बाँच्ने टनेल। बाँकी लेख यी दुईमध्ये एउटाका लागि जानाजान तिर्नेबारे हो, production मा बिल भेट्नुको सट्टा।

रनको आवृत्तिका आधारमा निर्णय गर्नुहोस्, चिनजानका आधारमा होइन

जब deploy दिनमा धेरै पटक आउँछन्, जब job ले एकभन्दा बढी निजी पोर्ट छुन्छ, वा जब प्लेटफर्म टोलीले पहिल्यै patching र credential rotation सम्हाल्छ, तब VPC वा अफिस नेटवर्कभित्र आफ्नै runner प्रयोग गर्नुहोस्। त्यो मेसिनमा job अरू कुनै host जस्तै firewall पछाडि resolve र route गर्छ। नेटवर्कको काम एक पटक, इन्स्टलको बेला हुन्छ, हरेक रनमा होइन।

जब पहुँच कहिलेकाहीँ मात्र हुन्छ र तपाईंको नेटवर्कमा credential राख्ने दीर्घजीवी agent चाहँदैन, तब टनेल job भित्रै बनाउनुहोस्। job केही मिनेटका लागि आफ्नै नेटवर्क client बन्छ र पछाडि केही छोड्दैन, जुन प्रायः पूरै उद्देश्य हो।

टनेल छान्नुअघि यसको लागत अनुमान गर्नुहोस्। हरेक रनले profile बनाउने, client सुरु गर्ने, तयारी र भत्काउने कामको मूल्य तिर्छ। जुन टनेल उठ्छ तर कहिल्यै प्रमाणित हुँदैन, त्यसले यस्तो deploy बनाउँछ जो आधा बाटोमा असफल हुन्छ र निजी अवस्था कसैले नसोचेको आकारमा छोड्छ। त्यसपछिको पुनः प्रयास विरलै सफा हुन्छ, र दोस्रो असफलता प्रायः client संस्करणमा थोपारिन्छ।

profile यसरी लेख्नुहोस् कि चरण रोकिन नसकोस्

profiles र credentials repository बाहिर राख्नुहोस् र तिनलाई secrets बाट त्यही चरणमा बनाउनुहोस् जसलाई चाहिन्छ। क्रमले job बाँच्ने वा नबाँच्ने तय गर्छ: sudo मुनि बनेको फाइल root को हुन्छ, र चरणको विशेषाधिकार नभएको shell त्यसपछि त्यसमा लेख्न सक्दैन।

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

त्यो ब्लकका दुवै विवरण पछिका चरणका लागि हुन्। umask 077 सँग profile मोड 0600 मा runner प्रयोगकर्ताको स्वामित्वमा आउँछ, sudo अझै पढ्न सक्छ, र client ले आफ्नो log runner सँग पहिल्यै भएको फाइलमा लेख्छ, त्यसैले तयारीको लूपले दोस्रो sudo बिना त्यो log पढ्न सक्छ। --writepid भत्काउनेले लक्ष्य गर्ने PID अभिलेख गर्छ।

client प्रमाणपत्रले प्रमाणित हुने profile लाई आफ्नो कुञ्जी त्यही तरिकाले लेखिएको चाहिन्छ, र static-challenge profile लाई मिल्ने auth मोड चाहिन्छ। DNS विकल्प push गर्ने profiles लाई Ubuntu र Debian मा openvpn-systemd-resolved चाहिन्छ, किनकि एक्लै push ले आधारभूत इमेजमा केही बदल्दैन।

तयारी एउटा जाँच हो, विश्राम होइन

निश्चित sleep ठ्याक्कै त्यतिबेलासम्म टिक्छ जबसम्म concentrator ढिलो हुँदैन, र त्यसपछि deploy चरण रुट बन्नुअघि नै चल्छ। असफलता त्यसपछि deploy उपकरणभित्र निजी host विरुद्ध timeout का रूपमा देखिन्छ, जसले टनेलबारे केही भन्दैन।

- 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

लूपले दुई कुरा हेर्छ किनकि तीमध्ये जुनसुकै टुटेको आधा हुन सक्छ। getent hosts ले push गरिएको resolver त्यो नामका लागि जवाफ दिन्छ भनी प्रमाणित गर्छ, र socket खुल्नुले deploy ले प्रयोग गर्ने पोर्टमा कोही सुनिरहेको छ भनी प्रमाणित गर्छ; केवल रुट भएको profile लाई शाब्दिक ठेगाना र मेटिएको getent हरफ चाहिन्छ।

लूप सकिएपछि, log नै एक्लो कुरा हो जसले तीन फरक खराबीलाई अलग गर्छ: अस्वीकृत प्रमाणपत्र, गलत auth मोड र कहिल्यै नआएको रुट। tail अघि फिल्टर गर्दा त्यो आउटपुट job अझै असफल हुँदै गर्दा पढ्न सकिने गरी छोटो रहन्छ। पहिलो त्रुटि पढ्नुहोस्, अन्तिम हरफ होइन, किनकि प्रमाणित हुन नसक्ने client लूपले हार नमानेसम्म आफैलाई दोहोर्याउँछ। ip -4 route show dev tun0 ले रुट push भयो कि भएन भन्ने सरल प्रश्नको जवाफ दिन्छ, र त्यही लूपभित्र एक हरफको मूल्य पर्छ।

भत्काउने र artifact को प्रश्न

job लाई if: always() ले सुरक्षित गरेको चरणले बन्द गर्नुहोस् जसले sudo kill "$(sudo cat "$RUNNER_TEMP/openvpn.pid")" र अरू केही चलाउँदैन। साझा आफ्नै runner मा कहिल्यै प्रक्रियाको नामले नमार्नुहोस्: अर्को job सँग एउटै binary र मिल्दा तर्क भएको client हुन सक्छ। त्यसपछि असफलता दोस्रो चलेको job मा पर्छ, र त्यसको log ले केही गल्ती नगरेको workflow तर्फ संकेत गर्छ।

सुरक्षा महत्त्वपूर्ण छ किनकि असफल deploy ले पनि जीवित टनेल छोड्छ। always() बिना सफाइको चरण ठ्याक्कै चाहिएको बेला छोडिन्छ, र अर्को रन पहिल्यै जोडिएको client सामु सुरु हुन्छ।

कुनै पनि डिजाइन अपनाउनुअघि एउटा प्रश्न बाँकी छ: build चरणलाई साँच्चै निजी रुट चाहिन्छ? पहिल्यै नेटवर्कभित्र बसेको deployment agent ले स्वीकृत artifact तान्न सक्छ, जसले साधारण builds लाई निजी बाटोबाट टाढा राख्छ। कम job जसले टनेल राख्छन् भनेको कम ठाउँ जहाँ पुरानो रुट लुक्न सक्छ।

सम्बन्धित लेखहरू