3 पॉइंट द्वारा GN⁺ 2024-09-22 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Kamal Proxy एक छोटा HTTP प्रॉक्सी है जो वेब एप्लिकेशन के सामने चलता है और मौजूदा ट्रैफिक को काटे बिना डिप्लॉयमेंट को नए इंस्टेंस पर स्विच करने के लिए डिजाइन किया गया है
  • नया इंस्टेंस kamal-proxy deploy से रजिस्टर किया जाता है, और प्रॉक्सी HTTP health check पास होने के बाद ही नए ट्रैफिक को उस इंस्टेंस पर रूट करता है
  • डिप्लॉय कमांड पुराने इंस्टेंस का सारा ट्रैफिक खत्म होने तक इंतजार करता है, इसलिए सफलतापूर्वक लौटने के बाद पुराने इंस्टेंस को चल रही requests को रोके बिना हटाया जा सकता है
  • एक ही प्रॉक्सी में कई एप्लिकेशन चलाने के लिए host-based routing, path-based routing, automatic TLS और manual TLS certificate निर्दिष्ट करने की सुविधा देता है
  • Kamal Proxy को Kamal डिप्लॉयमेंट टूल के हिस्से के रूप में डिजाइन किया गया है, लेकिन इसे standalone या दूसरे डिप्लॉयमेंट टूल्स के component के रूप में भी इस्तेमाल किया जा सकता है

Kamal Proxy क्या करता है

  • Kamal Proxy zero-downtime deployment coordination को आसान बनाने के लिए एक छोटा HTTP प्रॉक्सी है
  • वेब एप्लिकेशन को Kamal Proxy के पीछे चलाने पर, चल रहे ट्रैफिक को रोके बिना बदलाव deploy किए जा सकते हैं
  • इस व्यवहार के लिए एप्लिकेशन की ओर से किसी खास सहयोग की जरूरत नहीं होती
  • Kamal Proxy को container packaging और provisioning शामिल करने वाले Kamal के हिस्से के रूप में काम करने के लिए डिजाइन किया गया है
  • इसे standalone इस्तेमाल किया जा सकता है या दूसरे डिप्लॉयमेंट टूल के हिस्से के रूप में भी इस्तेमाल किया जा सकता है

रन और डिप्लॉयमेंट फ्लो

  • प्रॉक्सी इंस्टेंस को kamal-proxy run कमांड से चलाया जाता है
  • कोई config file नहीं है, और जब default values एप्लिकेशन के लिए फिट न हों तो options निर्दिष्ट किए जा सकते हैं
    • default HTTP port 80 है
    • दूसरे port पर चलाने के लिए kamal-proxy run --http-port 8080 इस्तेमाल करें
    • पूरी options kamal-proxy help run में देखी जा सकती हैं
  • ट्रैफिक को वेब एप्लिकेशन तक भेजने के लिए एप्लिकेशन इंस्टेंस को प्रॉक्सी में deploy करें
  • डिप्लॉय target instance को hostname:port format में निर्दिष्ट किया जाता है
    • उदाहरण: kamal-proxy deploy service1 --target web-1:3000
    • यह कमांड web-1:3000 को service1 service name से रजिस्टर करता है

zero-downtime स्विच करने का तरीका

  • नया इंस्टेंस रजिस्टर होते ही Kamal Proxy तुरंत HTTP health check चलाकर reachability और काम करने की स्थिति की जांच करता है
  • health check सफल होने पर नया ट्रैफिक नए इंस्टेंस पर रूट करना शुरू करता है
  • अगर नया इंस्टेंस उचित समय में healthy state में नहीं आ पाता, तो deploy command डिप्लॉयमेंट रोक देता है और non-zero exit code लौटाता है
  • हर डिप्लॉयमेंट पहले deploy किए गए इंस्टेंस का सारा ट्रैफिक नए इंस्टेंस को सौंप देता है
  • deploy command पुराने इंस्टेंस से सारा ट्रैफिक drain होने तक इंतजार करता है और फिर लौटता है
    • सफलतापूर्वक लौटने के बाद पुराने इंस्टेंस को हटाने पर भी चल रही requests नहीं टूटतीं
  • नया इंस्टेंस healthy state में होने पर ही ट्रैफिक लेता है, और पुराना इंस्टेंस पूरी तरह drain होने के बाद हटता है, इसलिए डिप्लॉयमेंट zero downtime में होता है

health check सेटिंग्स

  • default health check हर service के लिए प्रति सेकंड 1 बार /up पर GET request भेजता है
  • 200 response को healthy state माना जाता है
  • एप्लिकेशन के अनुसार health check बदलने के लिए deploy flags इस्तेमाल करें
    • --health-check-path
    • --health-check-port
    • --health-check-timeout
    • --health-check-interval
  • health check path बदलने का उदाहरण:
    • kamal-proxy deploy service1 --target web-1:3000 --health-check-path web/index.html
  • अगर health endpoint main service से अलग port पर expose होता है:
    • kamal-proxy deploy service1 --target web-1:3000 --health-check-port 8080

routing सुविधाएं

  • host-based routing

    • host-based routing इस्तेमाल करने से एक Kamal Proxy instance के जरिए उसी server पर मौजूद कई एप्लिकेशन तक ट्रैफिक route किया जा सकता है
    • डिप्लॉय करते समय कोई खास host निर्दिष्ट किया जा सकता है
    • kamal-proxy deploy service1 --target web-1:3000 --host app1.example.com
    • इस तरीके से deploy किए गए instance को सिर्फ निर्दिष्ट host का ट्रैफिक मिलता है
    • हर एप्लिकेशन के लिए अलग host निर्दिष्ट करने पर port conflict के बिना उसी server पर कई एप्लिकेशन चलाए जा सकते हैं
    • कोई खास host एक समय में केवल एक service को route कर सकता है
    • अगर service1 पहले से app1.example.com इस्तेमाल कर रहा है, तो service2 को उसी host पर deploy करने पर error लौटेगा
    • service1 हटाने के बाद service2 को उसी host पर deploy किया जा सकता है
  • path-based routing

    • path-based routing उन एप्लिकेशन में इस्तेमाल होता है जो request path के आधार पर ट्रैफिक को अलग-अलग services में बांटते हैं
    • services को अलग-अलग path prefixes के नीचे mount किया जा सकता है
    • /api से शुरू होने वाली requests को web-1 पर भेजने का उदाहरण: kamal-proxy deploy service1 --target web-1:3000 --path-prefix=/api
    • बाकी को web-2 पर भेजने का उदाहरण: kamal-proxy deploy service2 --target web-2:3000
    • default रूप से path prefix को upstream तक भेजने से पहले हटा दिया जाता है
    • /api/users/123 request web-1 को /users/123 के रूप में भेजी जाती है
    • original path को ज्यों का त्यों भेजने के लिए --strip-path-prefix=false निर्दिष्ट करें

TLS support

  • Kamal Proxy एप्लिकेशन के लिए TLS certificates अपने आप हासिल और renew कर सकता है
  • automatic TLS को डिप्लॉय के समय --tls flag जोड़कर enable किया जाता है
    • kamal-proxy deploy service1 --target web-1:3000 --host app1.example.com --tls
  • automatic TLS के लिए host निर्दिष्ट करना जरूरी है
    • यह किसी arbitrary hostname के लिए malicious तरीके से certificate request करने से रोकने की शर्त है
  • path-based routing में TLS option root path पर सेट करना चाहिए
    • उसी host के अलग path पर deploy की गई services root path पर निर्दिष्ट TLS settings इस्तेमाल करती हैं
  • अगर manually हासिल किया गया TLS certificate, अपनी certificate authority, या Cloudflare origin certificate install करना हो, तो certificate file और private key path सीधे निर्दिष्ट किए जा सकते हैं
    • --tls-certificate-path cert.pem
    • --tls-private-key-path key.pem

environment variables और build

  • Docker container चलाने जैसे environments में run options को environment variables के रूप में निर्दिष्ट किया जा सकता है
  • kamal-proxy run अगर environment variables सेट हों, तो हर option value environment variable से पढ़ता है
    • kamal-proxy run --http-port 8080
    • HTTP_PORT=8080 kamal-proxy run
  • अगर environment variable name मौजूदा environment से conflict करे, तो अलग पहचान के लिए KAMAL_PROXY_ prefix लगाया जा सकता है
    • KAMAL_PROXY_HTTP_PORT=8080 kamal-proxy run
  • local build working Go environment में make से किया जाता है
  • Docker container से build करने के लिए make docker इस्तेमाल करें
  • प्रॉक्सी command आजमाने के लिए Docker Compose configuration example folder में है

1 टिप्पणियां

 
GN⁺ 2024-09-22
Hacker News की राय
  • action के नाम के तौर पर deploy चुनना अजीब है
    यह पहले से ही बहुत overloaded term है, इसलिए “ऐप deploy हुआ? या proxy में deploy हुआ?” जैसी उलझन हो सकती है
    bind, intercept, या बस proxy जैसे शब्द भी इस्तेमाल किए जा सकते थे, समझ नहीं आता कि deploy क्यों

    • “deployed” का मतलब यह मानें कि वह running है और proxy में registered है
    • अगर incoming traffic proxy से आ रहा है, तो deploy का मतलब “proxy traffic नए app instance की ओर बहना शुरू हो गया” के अलावा और क्या हो सकता है, समझ नहीं आता
  • आजकल दूसरे servers से भी zero-downtime deployment आसानी से किया जा सकता है, इसलिए इसे एक अलग पूरी app बना देना दिलचस्प choice है
    उदाहरण के लिए Unix socket support करने वाली app + web proxy में सिर्फ file move करके downtime के बिना deploy किया जा सकता है
    यह atomic है, और curl से warm-up request भी भेजी जा सकती है
    पूरा registration system बनाना कुछ ज्यादा लगता है

    • यह Kamal(https://kamal-deploy.org) का बस बहुत छोटा हिस्सा है
      Kamal वह deployment tool है जिसका इस्तेमाल cloud से अपने hardware पर move करके लाखों dollars बचाने में किया गया था(https://basecamp.com/cloud-exit)
    • अगर आप इस तरीके के बारे में थोड़ा और समझा सकें तो अच्छा होगा
      अगर कोई reference post हो तो और सीखना चाहूंगा
  • यह मुख्य रूप से Docker Swarm में service container replace करते समय traffic कटने की मूल समस्या को handle करने की कोशिश जैसा लगता है
    Cloud 66 में JAMStack server बनाते समय मुझे यही समस्या आई थी, और अपने proxy के बजाय Caddy इस्तेमाल किया था; Traefik भी शायद पूरी तरह ठीक रहता
    Kamal ने k8s या k3s के बजाय Swarm क्यों चुना, पता नहीं, लेकिन complexity को कहीं न कहीं रहना ही होता है और उसे छिपाया नहीं जा सकता, इसलिए अंततः लगता है वे अपने proxy तक आ गए
    खुद इस्तेमाल नहीं किया है, लेकिन WebSockets, SSE, HTTP/3, तरह-तरह के compression और encryption support के पीछे लगातार भागना पड़ेगा, इसलिए मैं काफी skeptical हूं

    • Kamal ऐसा लगता है जैसे “Kubernetes बहुत complex है” वाली premise पर बना है, और उसी justification से शुरू करके Kubernetes जो काफी कुछ करता है उसे फिर से बना रहा है
      एक simple reverse proxy आखिरकार वही complexity absorb करता जा रहा है जिससे बचना था—यह वैसा example लगता है
      मुझे लगता है कि broad और scalable execution systems के competitors होने चाहिए, लेकिन Kamal उस complexity की ओर पीछे हटता हुआ काम लगता है जिससे वह बचना चाहता था
      desired state management framework के रूप में Kubernetes की क्षमता और flexibility उल्टे और ज्यादा उभरकर दिखती है
    • लगता है आप orchestration और proxy को मिला कर देख रहे हैं
      Docker का इस्तेमाल जारी रखते हुए भी proxy के लिए Caddy, Traefik, Envoy इस्तेमाल किए जा सकते हैं
      Kubernetes भी आखिरकार इन्हें अक्सर ingress controller के रूप में इस्तेमाल करता है
    • Kamal Docker Swarm इस्तेमाल करता है, यह आपने कहां देखा, मुझे नहीं पता
      देखने में तो ऐसा नहीं लगता कि यह Swarm इस्तेमाल करता है
    • Kamal सामान्य docker run command इस्तेमाल करता है, और इसमें Swarm या orchestration नहीं है
      मूल रूप से यह Capistrano का simple replacement है
    • अगर यही वजह है, तो लगता है इस topic पर बहुत basic research भी नहीं की गई
      container orchestration service का basics यह है कि ingress controller के जरिए connections और blue/green deployments handle किए जाते हैं
      और ज्यादा सटीक कहें तो ingress controller बस वह role name है जो उन असंख्य reverse proxies को दिया गया है जो सालों से, बल्कि कई मामलों में दशकों से, इस use case को handle करते आए हैं
  • क्या कोई संक्षेप में समझा सकता है कि zero-downtime deployment आम तौर पर कैसे काम करता है?
    मेरा अंदाजा है कि app के दो versions एक साथ running होते हैं और नया traffic नए version की ओर route होता है
    लेकिन अगर single database इस्तेमाल हो रहा हो और नए app version में schema change हो, तो startup पर migration script schema बदल देगी, जबकि पुराना app version पुराने schema की उम्मीद करेगा
    यह कैसे handle किया जाता है, जानना चाहता हूं

    • पहला step है migration और deployment को अलग करना
      कई frameworks code deploy के समय migration चलाते हैं, लेकिन असल में execution timing को manually control करना बेहतर होता है
      हर code version को current schema और future migration के बाद वाले schema—दोनों पर काम करना चाहिए, इसलिए यह असल में backward-compatible code बन जाता है
      flow होता है: “नया code deploy करें जो current/future schema दोनों पर काम करता हो → verify करें → migration चलाएं → verify करें → हट चुके schema को handle करने वाला code साफ करें”
    • migration backward-compatible होनी चाहिए, ताकि database schema app के दोनों versions को support कर सके
      zero-downtime deployment या rolling deployment करने के लिए यह extra cost चुकानी पड़ती है, और बड़ी कंपनियां आम तौर पर ऐसा ही करती हैं
    • जब सच में zero-downtime deployment की जरूरत हो, तब के तरीके दूसरे जवाबों ने समझाए हैं, लेकिन ज्यादातर organizations और ज्यादातर migrations में DB migration से होने वाला downtime व्यवहार में 0 से अलग नहीं होता
      खासकर अगर users किसी एक region तक सीमित हों और शांत time window चुनकर deploy किया जा सके, तो और भी
    • खुद इस्तेमाल नहीं किया है, लेकिन लगता है Xata ने कम से कम Postgres में DB migration के लिए काफी साफ समाधान बनाया है
      app के दो versions साथ-साथ चल सकते हैं
      https://xata.io/blog/multi-version-schema-migrations
    • सही है, किसी समय पर दोनों versions running होने ही चाहिए
      load balancer Server2 पर connections लेना शुरू करता है और Server1 पर नए connections लेना बंद करता है
      इसके बाद जब Server1 के सभी connections close हो जाते हैं, तो Server1 को disconnect कर दिया जाता है
      ये अलग-अलग servers हो सकते हैं, या एक ही server के कई workers भी हो सकते हैं
      उस दौरान, बाकी जवाबों की तरह, migration backward-compatible होनी चाहिए
  • Kamal 2 अभी RC(https://github.com/basecamp/kamal/releases) में है, और ऑटोमैटिक SSL सपोर्ट करेगा, जिससे एक ही सर्वर पर कई ऐप्स को Kamal से आसानी से चलाया जा सकेगा—इसे लेकर उत्सुकता है

    • यह autocert पैकेज का उपयोग करता है, जो लगभग न्यूनतम implementation जैसा है
      यह कमजोर है, और Let's Encrypt की issuance limit व concurrent certificate limit की वजह से proxy instances को horizontally scale करना मुश्किल है
      Caddy/Certmagic shared storage में data लिखकर सिर्फ एक certificate issue करते हैं और सभी instances को storage के जरिए reuse/coordinate करवाते हैं, जिससे यह समस्या हल होती है
      issuer fallback, issuance limit से बचाव, और ARI support भी नहीं है
      upstream उपलब्ध होने तक requests को पकड़े रखना भी Caddy में reverse_proxy पर try_duration और try_interval सेट करने से अच्छी तरह संभल जाता है
      proxy header handling भी trusted IPs को ध्यान में नहीं रखती, इसलिए अगर इसे enable किया जाए तो कोई भी X-Forwarded-For सेट करके IP spoof कर सकता है
      अच्छा है कि default में यह off है, लेकिन कोई warning भी नहीं है
      मैं समझता हूँ कि simplicity ही लक्ष्य है, लेकिन मौजूदा हालत में यह अधपका है और बेहतर विकल्प इतने ज्यादा हैं कि इसे production में सचमुच इस्तेमाल करने का मन नहीं होगा
  • मुझे ठीक से समझ नहीं आ रहा कि इसे कैसे इस्तेमाल करना है, और लगता है कि मैं कुछ miss कर रहा हूँ
    example web service की 4 replicas शुरू करता है
    अगर उनमें से example-web-1 जैसे किसी एक replica पर deploy करके service बनाई जा सकती है, तो बाकी 3 replicas क्या कर रहे हैं, समझ नहीं आता
    web को update करके zero-downtime deploy करना हो तो शायद web service में build command चलानी होगी, किसी तरह इस service को start करना होगा, और फिर नए target के लिए deploy चलाना होगा
    लेकिन docker compose up --build --force-recreate web चलाने पर existing replicas down हो जाते हैं, तो सब बेकार हो जाता है

    • पहले सवाल में बाकी replicas को Docker VIP या DNS request में कई IP लौटाने के तरीके से load balance करता है[0]
      मैंने check नहीं किया कि यह proxy DNS request से लौटे multiple records पर balance करती है या नहीं, लेकिन कम से कम VIP-based load balancing हो तो यह उम्मीद के मुताबिक काम करेगा
      दूसरा update वाला हिस्सा कम clear है
      शायद expectation यह हो कि उसी network में किसी अलग नाम की service चलाकर kamal-proxy deploy किया जाए
      service name में version number डालने जैसा तरीका हो सकता है, और अगर जल्दी rollback करना हो तो previous version को hot state में बनाए रखना भी समझ में आता है
      [0]: https://docs.docker.com/reference/compose-file/deploy/#endpo...
    • समझ नहीं आता कि बस k8s rollout restart deployment इस्तेमाल न करने की वजह क्या है
      या फिर DNS या router को दो backends के बीच switch कर सकते हैं
  • सोच रहा हूँ कि क्या यह traffic pause pattern implement करता है
    इसमें proxy traffic को कुछ seconds के लिए effectively रोक देता है, जिससे incoming requests सामान्य से कुछ seconds ज्यादा समय लेती दिखती हैं, लेकिन छोटी delay के बाद complete हो जाती हैं
    उन कुछ seconds में छोटी DB migration या 5 seconds के अंदर पूरी हो सकने वाली थोड़ी ज्यादा complex blocking infra change चला सकते हैं

    • जानना चाहूँगा कि किसी ने इसे real production environment में किया है या नहीं
      यह काफी risky लगता है, और मैंने app server company में कई साल काम किया है लेकिन यह pattern पहली बार सुन रहा हूँ
      हालांकि Django के co-creator ने कई deployments देखे होंगे, इसलिए इसे यूँ ही dismiss करना मुश्किल है
    • सच कहूँ तो यह dangerously living pattern जैसा लगता है
    • Caddy यह करता है
      याद है कि पहले इस topic पर बात हुई थी
  • जानना चाहता हूँ कि Traefik या किसी दूसरे proven tool का उपयोग करने के बजाय अपना proxy बनाने का कारण कहाँ explain किया गया है

    • असल में इस “v2.0.0” pre-release से पहले तक Traefik ही इस्तेमाल हो रहा था
      क्यों बदला और खुद implement करने का फैसला किया, इसका context PR में है
      https://github.com/basecamp/kamal/pull/940
    • यहाँ कारणों को थोड़ा summarize करने की कोशिश की थी https://nts.strzibny.name/kamal-proxy/
      लेकिन लगता है Traefik के अलावा बाकी चीजों से official comparison कभी publish नहीं किया गया
  • जानना चाहता हूँ कि timeout configure करने का कोई तरीका है या नहीं
    https://github.com/basecamp/kamal-proxy/blob/main/internal/s...
    https://github.com/basecamp/kamal-proxy/blob/main/internal/s...
    https://blog.cloudflare.com/exposing-go-on-the-internet/

  • यह NIH है. इससे ज्यादा कहने को कुछ नहीं