तुमचा deploy टप्पा एखाद्या अंतर्गत hostname वर अडकतो, तर तोच कमांड तुमच्या लॅपटॉपवरून लगेच उत्तर देतो, आणि दोन्ही मशीनवरील client build सारखाच असतो. job GitHub-hosted runner वर चालतो: त्या एका job साठी GitHub च्या क्लाउडमध्ये तयार केलेली आभासी मशीन, तुमच्या खाजगी पत्ता जागेत कोणताही रूट नाही, अंतर्गत झोनसाठी resolver नोंद नाही आणि खाजगी endpoint स्वीकारेल असे कोणतेही प्रमाणपत्र नाही. या मर्यादेत फक्त दोन रचना बसतात, आणि workflow पुन्हा न बांधता त्यातली एकही नंतर सुरू करता येत नाही. YAML च्या पहिल्या ओळीपूर्वी त्यातून निवडा, कारण नंतर स्थलांतर पहिल्या प्रयत्नापेक्षा जास्त महाग पडते.

निवड त्या runner मधली आहे जो नेटवर्क आधीच संपते तिथे ठेवला जातो आणि त्या टनेलमधली जी एका job इतकी टिकते. दोन्ही वर्षानुवर्षे production deploy वाहतात, आणि वेगवेगळ्या पद्धतीने अपयशी होतात.

सीमा प्रत्यक्षात कुठे आहे

तुम्ही लॅपटॉपवर जे काही इन्स्टॉल करता ते लॅपटॉपवर थांबते, आणि job दरम्यान जे इन्स्टॉल करता ते runner सोबत नाहीसे होते. client ला रनमध्ये जोडून ठेवता येईल असे कायमचे नेटवर्क namespace नाही, म्हणून प्रत्येक रन त्याच अपोह्य अवस्थेतून सुरू होते. Azure ही सीमा Microsoft-hosted agents साठी नोंदवते, जिथे खाजगी नेटवर्कमधील VPN आणि ExpressRoute दुवे समर्थित नाहीत, आणि GitHub-hosted 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 जे टनेल धरतात म्हणजे कमी जागा जिथे जुना रूट लपू शकतो.

संबंधित लेख