ज़ीरो डाउनटाइम डिप्लॉयमेंट के लिए न्यूनतम HTTP प्रॉक्सी, Kamal Proxy
(github.com/basecamp)- 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में देखी जा सकती हैं
- default HTTP port
- ट्रैफिक को वेब एप्लिकेशन तक भेजने के लिए एप्लिकेशन इंस्टेंस को प्रॉक्सी में deploy करें
- डिप्लॉय target instance को
hostname:portformat में निर्दिष्ट किया जाता है- उदाहरण:
kamal-proxy deploy service1 --target web-1:3000 - यह कमांड
web-1:3000कोservice1service name से रजिस्टर करता है
- उदाहरण:
zero-downtime स्विच करने का तरीका
- नया इंस्टेंस रजिस्टर होते ही Kamal Proxy तुरंत HTTP health check चलाकर reachability और काम करने की स्थिति की जांच करता है
- health check सफल होने पर नया ट्रैफिक नए इंस्टेंस पर रूट करना शुरू करता है
- अगर नया इंस्टेंस उचित समय में healthy state में नहीं आ पाता, तो
deploycommand डिप्लॉयमेंट रोक देता है और non-zero exit code लौटाता है - हर डिप्लॉयमेंट पहले deploy किए गए इंस्टेंस का सारा ट्रैफिक नए इंस्टेंस को सौंप देता है
deploycommand पुराने इंस्टेंस से सारा ट्रैफिक drain होने तक इंतजार करता है और फिर लौटता है- सफलतापूर्वक लौटने के बाद पुराने इंस्टेंस को हटाने पर भी चल रही requests नहीं टूटतीं
- नया इंस्टेंस healthy state में होने पर ही ट्रैफिक लेता है, और पुराना इंस्टेंस पूरी तरह drain होने के बाद हटता है, इसलिए डिप्लॉयमेंट zero downtime में होता है
health check सेटिंग्स
- default health check हर service के लिए प्रति सेकंड 1 बार
/upपरGETrequest भेजता है 200response को healthy state माना जाता है- एप्लिकेशन के अनुसार health check बदलने के लिए
deployflags इस्तेमाल करें--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/123requestweb-1को/users/123के रूप में भेजी जाती है- original path को ज्यों का त्यों भेजने के लिए
--strip-path-prefix=falseनिर्दिष्ट करें
TLS support
- Kamal Proxy एप्लिकेशन के लिए TLS certificates अपने आप हासिल और renew कर सकता है
- automatic TLS को डिप्लॉय के समय
--tlsflag जोड़कर 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 में
runoptions को environment variables के रूप में निर्दिष्ट किया जा सकता है kamal-proxy runअगर environment variables सेट हों, तो हर option value environment variable से पढ़ता हैkamal-proxy run --http-port 8080HTTP_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
examplefolder में है
1 टिप्पणियां
Hacker News की राय
action के नाम के तौर पर deploy चुनना अजीब है
यह पहले से ही बहुत overloaded term है, इसलिए “ऐप deploy हुआ? या proxy में deploy हुआ?” जैसी उलझन हो सकती है
bind,intercept, या बसproxyजैसे शब्द भी इस्तेमाल किए जा सकते थे, समझ नहीं आता किdeployक्योंआजकल दूसरे servers से भी zero-downtime deployment आसानी से किया जा सकता है, इसलिए इसे एक अलग पूरी app बना देना दिलचस्प choice है
उदाहरण के लिए Unix socket support करने वाली app + web proxy में सिर्फ file move करके downtime के बिना deploy किया जा सकता है
यह atomic है, और
curlसे warm-up request भी भेजी जा सकती हैपूरा registration system बनाना कुछ ज्यादा लगता है
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 हूं
एक simple reverse proxy आखिरकार वही complexity absorb करता जा रहा है जिससे बचना था—यह वैसा example लगता है
मुझे लगता है कि broad और scalable execution systems के competitors होने चाहिए, लेकिन Kamal उस complexity की ओर पीछे हटता हुआ काम लगता है जिससे वह बचना चाहता था
desired state management framework के रूप में Kubernetes की क्षमता और flexibility उल्टे और ज्यादा उभरकर दिखती है
Docker का इस्तेमाल जारी रखते हुए भी proxy के लिए Caddy, Traefik, Envoy इस्तेमाल किए जा सकते हैं
Kubernetes भी आखिरकार इन्हें अक्सर ingress controller के रूप में इस्तेमाल करता है
देखने में तो ऐसा नहीं लगता कि यह Swarm इस्तेमाल करता है
docker runcommand इस्तेमाल करता है, और इसमें Swarm या orchestration नहीं हैमूल रूप से यह Capistrano का simple replacement है
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 किया जाता है, जानना चाहता हूं
कई 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 साफ करें”
zero-downtime deployment या rolling deployment करने के लिए यह extra cost चुकानी पड़ती है, और बड़ी कंपनियां आम तौर पर ऐसा ही करती हैं
खासकर अगर users किसी एक region तक सीमित हों और शांत time window चुनकर deploy किया जा सके, तो और भी
app के दो versions साथ-साथ चल सकते हैं
https://xata.io/blog/multi-version-schema-migrations
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
webservice की 4 replicas शुरू करता हैअगर उनमें से
example-web-1जैसे किसी एक replica पर deploy करके service बनाई जा सकती है, तो बाकी 3 replicas क्या कर रहे हैं, समझ नहीं आताwebको update करके zero-downtime deploy करना हो तो शायदwebservice में build command चलानी होगी, किसी तरह इस service को start करना होगा, और फिर नए target के लिए deploy चलाना होगालेकिन
docker compose up --build --force-recreate webचलाने पर existing replicas down हो जाते हैं, तो सब बेकार हो जाता हैमैंने 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 चला सकते हैं
यह काफी risky लगता है, और मैंने app server company में कई साल काम किया है लेकिन यह pattern पहली बार सुन रहा हूँ
हालांकि Django के co-creator ने कई deployments देखे होंगे, इसलिए इसे यूँ ही dismiss करना मुश्किल है
याद है कि पहले इस topic पर बात हुई थी
जानना चाहता हूँ कि Traefik या किसी दूसरे proven tool का उपयोग करने के बजाय अपना proxy बनाने का कारण कहाँ explain किया गया है
क्यों बदला और खुद implement करने का फैसला किया, इसका context PR में है
https://github.com/basecamp/kamal/pull/940
लेकिन लगता है 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 है. इससे ज्यादा कहने को कुछ नहीं