3 คะแนน โดย GN⁺ 2024-09-22 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Kamal Proxy เป็น HTTP proxy ขนาดเล็กที่ทำงานอยู่หน้าเว็บแอปพลิเคชัน ออกแบบมาเพื่อสลับการดีพลอยไปยังอินสแตนซ์ใหม่โดยไม่ตัดทราฟฟิกที่กำลังดำเนินอยู่
  • อินสแตนซ์ใหม่จะถูกลงทะเบียนด้วย kamal-proxy deploy และพร็อกซีจะ route ทราฟฟิกใหม่ไปยังอินสแตนซ์นั้นก็ต่อเมื่อผ่าน HTTP health check แล้วเท่านั้น
  • คำสั่งดีพลอยจะรอจนกว่าทราฟฟิกของอินสแตนซ์เดิมจะ drain ออกหมด ดังนั้นหลังจากคำสั่งคืนค่าสำเร็จแล้ว จึงสามารถลบอินสแตนซ์เดิมได้ โดยไม่ขัดจังหวะ request ที่กำลังดำเนินอยู่
  • เพื่อให้รันหลายแอปพลิเคชันบนพร็อกซีตัวเดียวได้ มีฟีเจอร์ host-based routing, path-based routing, TLS อัตโนมัติ และการระบุใบรับรอง TLS แบบ manual
  • Kamal Proxy ถูกออกแบบมาเป็นส่วนหนึ่งของเครื่องมือดีพลอย Kamal แต่ก็สามารถใช้แบบ standalone หรือเป็นคอมโพเนนต์ของเครื่องมือดีพลอยอื่นได้เช่นกัน

Kamal Proxy ทำอะไร

  • Kamal Proxy เป็น HTTP proxy ขนาดเล็กสำหรับทำให้การประสานงานดีพลอยแบบไม่มีดาวน์ไทม์ง่ายขึ้น
  • เมื่อรันเว็บแอปพลิเคชันไว้หลัง Kamal Proxy จะสามารถดีพลอยการเปลี่ยนแปลงได้โดยไม่หยุดทราฟฟิกที่กำลังดำเนินอยู่
  • พฤติกรรมนี้ไม่ต้องอาศัยความร่วมมือพิเศษใด ๆ จากฝั่งแอปพลิเคชัน
  • Kamal Proxy ถูกออกแบบมาให้ทำงานเป็นส่วนหนึ่งของ Kamal ซึ่งครอบคลุมการทำ container packaging และ provisioning
  • สามารถใช้แบบ standalone หรือใช้เป็นส่วนหนึ่งของเครื่องมือดีพลอยอื่นได้

การรันและโฟลว์การดีพลอย

  • อินสแตนซ์พร็อกซีรันด้วยคำสั่ง kamal-proxy run
  • ไม่มีไฟล์ตั้งค่า และสามารถระบุ option ได้เมื่อค่า default ไม่เหมาะกับแอปพลิเคชัน
    • พอร์ต HTTP default คือ 80
    • หากต้องการรันบนพอร์ตอื่น ให้ใช้ kamal-proxy run --http-port 8080
    • ดู option ทั้งหมดได้ที่ kamal-proxy help run
  • หากต้องการส่งทราฟฟิกไปยังเว็บแอปพลิเคชัน ให้ deploy อินสแตนซ์แอปพลิเคชันไปยังพร็อกซี
  • อินสแตนซ์เป้าหมายสำหรับดีพลอยระบุในรูปแบบ hostname:port
    • ตัวอย่าง: kamal-proxy deploy service1 --target web-1:3000
    • คำสั่งนี้ลงทะเบียน web-1:3000 ภายใต้ชื่อ service service1

วิธีสลับแบบไม่มีดาวน์ไทม์

  • เมื่อมีการลงทะเบียนอินสแตนซ์ใหม่ Kamal Proxy จะรัน HTTP health check ทันทีเพื่อตรวจสอบว่าสามารถเข้าถึงและทำงานได้หรือไม่
  • หาก health check สำเร็จ จะเริ่ม route ทราฟฟิกใหม่ไปยังอินสแตนซ์ใหม่
  • หากอินสแตนซ์ใหม่ไม่เข้าสู่สถานะ healthy ภายในเวลาที่เหมาะสม คำสั่ง deploy จะหยุดการดีพลอยและคืน exit code ที่ไม่ใช่ 0
  • การดีพลอยแต่ละครั้งจะย้ายทราฟฟิกทั้งหมดจากอินสแตนซ์ที่ดีพลอยไว้ก่อนหน้าไปยังอินสแตนซ์ใหม่
  • คำสั่ง deploy จะรอจนกว่าทราฟฟิกจะออกจากอินสแตนซ์เดิมหมดแล้วจึงคืนค่า
    • หลังจากคืนค่าสำเร็จแล้ว สามารถลบอินสแตนซ์เดิมได้โดยไม่ตัด request ที่กำลังดำเนินอยู่
  • เนื่องจากอินสแตนซ์ใหม่จะรับทราฟฟิกเฉพาะเมื่ออยู่ในสถานะ healthy และอินสแตนซ์เดิมจะถูกลบหลังจาก drain สมบูรณ์แล้ว การดีพลอยจึงดำเนินไปแบบ ไม่มีดาวน์ไทม์

การตั้งค่า health check

  • health check default จะส่ง request GET ไปที่ /up วินาทีละ 1 ครั้งสำหรับแต่ละ service
  • ถือว่า response 200 เป็นสถานะ healthy
  • หากต้องการปรับ health check ให้เหมาะกับแอปพลิเคชัน ให้ใช้ flag ของ deploy
    • --health-check-path
    • --health-check-port
    • --health-check-timeout
    • --health-check-interval
  • ตัวอย่างการเปลี่ยน path สำหรับ health check:
    • kamal-proxy deploy service1 --target web-1:3000 --health-check-path web/index.html
  • กรณี expose health endpoint บนพอร์ตที่ต่างจาก service หลัก:
    • kamal-proxy deploy service1 --target web-1:3000 --health-check-port 8080

ฟีเจอร์ routing

  • Host-based routing

    • การใช้ host-based routing ทำให้สามารถ route ทราฟฟิกจาก Kamal Proxy อินสแตนซ์เดียวไปยังหลายแอปพลิเคชันบนเซิร์ฟเวอร์เดียวกันได้
    • ระบุ host เฉพาะขณะดีพลอยได้
    • kamal-proxy deploy service1 --target web-1:3000 --host app1.example.com
    • อินสแตนซ์ที่ดีพลอยด้วยวิธีนี้จะรับเฉพาะทราฟฟิกของ host ที่ระบุเท่านั้น
    • หากระบุ host แยกให้แต่ละแอปพลิเคชัน ก็สามารถรันหลายแอปพลิเคชันบนเซิร์ฟเวอร์เดียวกันได้โดยไม่เกิด port conflict
    • host หนึ่ง ๆ สามารถ route ไปยัง service ได้เพียงหนึ่งรายการในเวลาเดียวกัน
    • หาก service1 ใช้ app1.example.com อยู่แล้ว เมื่อ service2 ถูกดีพลอยด้วย host เดียวกันจะคืน error
    • หลังจากลบ service1 แล้ว จึงสามารถดีพลอย service2 ไปยัง host เดียวกันได้
  • Path-based routing

    • path-based routing ใช้กับแอปพลิเคชันที่แบ่งทราฟฟิกไปยัง service ต่าง ๆ ตาม path ของ request
    • service สามารถ mount อยู่ใต้ path prefix ที่แตกต่างกันได้
    • ตัวอย่างการส่ง request ที่ขึ้นต้นด้วย /api ไปยัง 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
    • request /api/users/123 จะถูกส่งไปยัง web-1 เป็น /users/123
    • หากต้องการส่งต่อ path เดิมตามเดิม ให้ระบุ --strip-path-prefix=false

การรองรับ TLS

  • Kamal Proxy สามารถขอรับและต่ออายุใบรับรอง TLS สำหรับแอปพลิเคชันได้โดยอัตโนมัติ
  • เปิดใช้ TLS อัตโนมัติได้โดยเพิ่ม flag --tls ตอนดีพลอย
    • kamal-proxy deploy service1 --target web-1:3000 --host app1.example.com --tls
  • TLS อัตโนมัติต้องมีการระบุ host
    • เป็นเงื่อนไขเพื่อป้องกันไม่ให้มีการร้องขอใบรับรองสำหรับ hostname ใด ๆ โดยเจตนาร้าย
  • ใน path-based routing ต้องตั้งค่า option TLS ที่ root path
    • service ที่ดีพลอยไปยัง path อื่นของ host เดียวกันจะใช้การตั้งค่า TLS ที่ระบุไว้ที่ root path
  • หากต้องติดตั้งใบรับรอง TLS ที่ขอรับมาแบบ manual, certificate authority ของตนเอง หรือ Cloudflare origin certificate สามารถระบุ path ของไฟล์ใบรับรองและ private key ได้โดยตรง
    • --tls-certificate-path cert.pem
    • --tls-private-key-path key.pem

Environment variable และการ build

  • ใน environment เช่นการรัน Docker container สามารถระบุ option ของ run ผ่าน environment variable ได้
  • kamal-proxy run จะอ่านค่าของแต่ละ option จาก environment variable หากมีการตั้งค่าไว้
    • kamal-proxy run --http-port 8080
    • HTTP_PORT=8080 kamal-proxy run
  • หากชื่อ environment variable ชนกับ environment เดิม สามารถเพิ่ม prefix KAMAL_PROXY_ เพื่อแยกความแตกต่างได้
    • KAMAL_PROXY_HTTP_PORT=8080 kamal-proxy run
  • การ build ในเครื่องทำด้วย make บน environment Go ที่ใช้งานได้
  • หากต้องการ build ด้วย Docker container ให้ใช้ make docker
  • การตั้งค่า Docker Compose สำหรับลองใช้คำสั่งพร็อกซีอยู่ในโฟลเดอร์ example

1 ความคิดเห็น

 
GN⁺ 2024-09-22
ความคิดเห็นจาก Hacker News
  • การเลือกชื่อการกระทำว่า deploy ดูแปลก
    คำนี้ถูกใช้จนมีความหมายล้นอยู่แล้ว น่าจะทำให้สับสนแบบว่า “แอปถูก deploy แล้วเหรอ? หรือ deploy ไปที่พร็อกซีกันแน่?”
    น่าจะใช้คำอย่าง bind, intercept หรือแค่ proxy ก็ได้ แต่ไม่เข้าใจว่าทำไมต้องเป็น deploy

    • “ถูก deploy แล้ว” ให้มองว่าหมายถึงกำลังรันอยู่และ ถูกลงทะเบียนไว้กับพร็อกซี
    • ถ้าทราฟฟิกขาเข้ามาจากพร็อกซี ก็ไม่เห็นว่า deploy จะหมายถึงอะไรได้นอกจาก “ทราฟฟิกของพร็อกซีเริ่มไหลไปยังอินสแตนซ์แอปใหม่แล้ว”
  • ทุกวันนี้ทำ การ deploy แบบไม่หยุดให้บริการ ด้วยเซิร์ฟเวอร์แบบอื่น ๆ ก็ทำได้ง่าย เลยน่าสนใจที่เลือกทำสิ่งนี้เป็นแอปแยกทั้งตัว
    เช่น แอป+เว็บพร็อกซีที่รองรับ Unix socket สามารถทำแบบไม่หยุดให้บริการได้เพียงแค่ย้ายไฟล์
    เป็นแบบ atomic และยังส่งคำขอวอร์มอัปด้วย curl ได้ด้วย
    การทำไปถึงระบบลงทะเบียนดูจะเกินจำเป็น

    • นี่เป็นแค่ส่วนเล็กมาก ๆ ของ Kamal(https://kamal-deploy.org) เท่านั้น
      Kamal เป็นเครื่องมือ deploy ที่ใช้ตอนย้ายจากคลาวด์ไปยังฮาร์ดแวร์ของตัวเอง และช่วยประหยัดเงินได้หลายล้านดอลลาร์(https://basecamp.com/cloud-exit)
    • ถ้าอธิบายวิธีนี้เพิ่มได้จะดีมาก
      ถ้ามีบทความอ้างอิงก็อยากเรียนรู้เพิ่มเติม
  • ดูเหมือนว่าสิ่งนี้ตั้งใจจัดการปัญหาพื้นฐานที่ทราฟฟิกสะดุดเมื่อสลับคอนเทนเนอร์ของบริการใน Docker Swarm เป็นหลัก
    ตอนทำเซิร์ฟเวอร์ JAMStack ที่ Cloud 66 ก็เคยเจอปัญหาเดียวกัน และใช้ Caddy แทนการทำพร็อกซีเอง ส่วน Traefik ก็น่าจะเหมาะพอเช่นกัน
    ไม่รู้ว่าทำไม Kamal ถึงเลือก Swarm แทน k8s หรือ k3s แต่ความซับซ้อนต้องไปอยู่ที่ไหนสักแห่งและซ่อนไม่ได้ สุดท้ายเลยเหมือนจะไปจบที่พร็อกซีของตัวเอง
    แม้ยังไม่เคยลองใช้เอง แต่ค่อนข้างกังขา เพราะน่าจะต้องคอยวิ่งตามการรองรับ WebSockets, SSE, HTTP/3 รวมถึงการบีบอัดและการเข้ารหัสสารพัดแบบไปเรื่อย ๆ

    • Kamal ให้ความรู้สึกว่าสร้างขึ้นบนสมมติฐานว่า “Kubernetes ซับซ้อนเกินไป” และเริ่มจากการให้เหตุผลนั้น แล้วก็สร้างหลายส่วนที่ Kubernetes ทำอยู่ขึ้นมาใหม่
      ดูเป็นตัวอย่างของ reverse proxy ที่เริ่มต้นแบบเรียบง่าย แต่สุดท้ายค่อย ๆ ดูดซับความซับซ้อนที่ตั้งใจหลีกเลี่ยง
      ผมคิดว่าระบบรันไทม์ที่กว้างและขยายได้ควรมีคู่แข่ง แต่ Kamal ดูเหมือนเป็นงานที่ถอยกลับเข้าสู่ความซับซ้อนที่พยายามหลีกเลี่ยง
      กลับยิ่งทำให้ความสามารถและความยืดหยุ่นของ Kubernetes ในฐานะเฟรมเวิร์ก จัดการสถานะที่ต้องการ เด่นชัดขึ้น
    • ดูเหมือนกำลังเอา orchestration กับพร็อกซีมาปนกัน
      คุณยังใช้ Docker ต่อไปได้และใช้ Caddy, Traefik, Envoy เป็นพร็อกซีได้
      ใน Kubernetes เองสุดท้ายก็มักใช้สิ่งเหล่านี้เป็น ingress controller อยู่ดี
    • ไม่รู้ว่าเห็นจากไหนว่า Kamal ใช้ Docker Swarm
      ดูแล้วไม่น่าจะใช้ Swarm
    • Kamal ใช้คำสั่ง docker run ธรรมดา และไม่มี Swarm หรือ orchestration
      โดยพื้นฐานแล้วเป็นเครื่องมือง่าย ๆ ที่มาแทน Capistrano
    • ถ้านั่นคือเหตุผล ก็รู้สึกว่าไม่ได้ค้นคว้าพื้นฐานเกี่ยวกับหัวข้อนี้เลย
      พื้นฐานของบริการ container orchestration คือการใช้ ingress controller เพื่อจัดการการเชื่อมต่อและการ deploy แบบ blue/green
      พูดให้แม่นกว่านั้น ingress controller คือชื่อบทบาทที่มอบให้ reverse proxy จำนวนมาก ซึ่งรับมือ use case นี้มาหลายปี หรือยาวไปถึงหลายสิบปีแล้ว
  • ถ้าอธิบายสั้น ๆ ได้ว่าโดยทั่วไป การ deploy แบบไม่หยุดให้บริการ ทำงานอย่างไรจะดีมาก
    เดาว่าเป็นโครงสร้างที่แอปสองเวอร์ชันรันพร้อมกัน และทราฟฟิกใหม่ถูก route ไปยังเวอร์ชันใหม่
    แต่ถ้าใช้ฐานข้อมูลเดียว และแอปเวอร์ชันใหม่มีการเปลี่ยน schema สคริปต์ migration ตอนเริ่มต้นก็คงเปลี่ยน schema แล้วแอปเวอร์ชันเก่าก็คาดหวัง schema แบบเดิม
    เลยสงสัยว่าจัดการเรื่องนี้อย่างไร

    • ขั้นแรกคือ แยก migration ออกจากการ deploy
      หลายเฟรมเวิร์กรัน migration ตอน deploy โค้ด แต่ในทางปฏิบัติควรควบคุมเวลารันด้วยตัวเองจะดีกว่า
      โค้ดแต่ละเวอร์ชันต้องทำงานได้ทั้งกับ schema ปัจจุบันและ schema หลัง migration ในอนาคต จึงกลายเป็นโค้ดที่ backward compatible โดยปริยาย
      โฟลว์จะเป็น “deploy โค้ดใหม่ที่ทำงานได้ทั้งกับ schema ปัจจุบัน/อนาคต → ตรวจสอบ → รัน migration → ตรวจสอบ → เก็บกวาดโค้ดที่รองรับ schema ที่หายไปแล้ว”
    • migration ต้อง backward compatible เพื่อให้ schema ฐานข้อมูลรองรับแอปได้ทั้งสองเวอร์ชัน
      นี่คือต้นทุนเพิ่มเติมที่ต้องจ่ายหากต้องการ deploy แบบไม่หยุดให้บริการหรือ rolling deploy และบริษัทใหญ่ ๆ โดยทั่วไปก็ทำแบบนี้
    • คำตอบอื่น ๆ อธิบายวิธีเมื่อจำเป็นต้อง deploy แบบไม่หยุดให้บริการจริง ๆ ไว้แล้ว แต่สำหรับองค์กรส่วนใหญ่และ migration ส่วนใหญ่ downtime จาก DB migration แทบแยกไม่ออกจาก 0
      โดยเฉพาะถ้ากลุ่มผู้ใช้เป็นระดับภูมิภาค และสามารถเลือก deploy ในช่วงเวลาที่เงียบได้ ก็ยิ่งเป็นแบบนั้น
    • ยังไม่เคยลองใช้เอง แต่ Xata ดูเหมือนจะทำโซลูชันสำหรับ DB migration ไว้ค่อนข้างเรียบร้อย อย่างน้อยก็สำหรับ Postgres
      แอปสองเวอร์ชันสามารถรันพร้อมกันได้
      https://xata.io/blog/multi-version-schema-migrations
    • ใช่แล้ว ณ ช่วงเวลาหนึ่งต้องมีทั้งสองเวอร์ชันรันอยู่พร้อมกัน
      load balancer จะเริ่มรับการเชื่อมต่อที่ Server2 และไม่รับการเชื่อมต่อใหม่ที่ Server1
      จากนั้นเมื่อการเชื่อมต่อทั้งหมดของ Server1 ปิดลงแล้ว ก็ถอด Server1 ออก
      อาจเป็นคนละเซิร์ฟเวอร์กัน หรือเป็นหลาย worker ในเซิร์ฟเวอร์เดียวกันก็ได้
      ในช่วงเวลานั้น migration ต้อง backward compatible ตามที่คำตอบอื่น ๆ บอกไว้
  • Kamal 2 ตอนนี้เป็น RC (https://github.com/basecamp/kamal/releases) และรองรับ SSL อัตโนมัติ ทำให้น่าตั้งตารอ เพราะจะทำให้รันหลายแอปด้วย Kamal บนเซิร์ฟเวอร์เดียวได้ง่ายขึ้น

    • ใช้แพ็กเกจ autocert ซึ่งแทบจะเป็นการใช้งานแบบขั้นต่ำสุด
      เปราะบาง และเพราะข้อจำกัดการออกใบรับรองของ Let's Encrypt กับข้อจำกัดใบรับรองพร้อมกัน จึงทำให้ขยายอินสแตนซ์พร็อกซีในแนวนอนได้ยาก
      Caddy/Certmagic แก้ปัญหานี้ด้วยการเขียนข้อมูลลง shared storage เพื่อออกใบรับรองเพียงใบเดียว แล้วให้อินสแตนซ์ทั้งหมดนำกลับมาใช้และประสานงานกันผ่าน storage นั้น
      ไม่มีการสลับผู้ออกใบรับรอง, การเลี่ยงข้อจำกัดการออกใบรับรอง, หรือการรองรับ ARI
      ส่วนการค้าง request ไว้จนกว่า upstream จะพร้อม Caddy ก็จัดการได้ดีถ้าตั้ง try_duration และ try_interval ใน reverse_proxy
      การจัดการ proxy header ก็ไม่คำนึงถึง IP ที่เชื่อถือได้ ดังนั้นถ้าเปิดใช้ ใครก็สามารถตั้ง X-Forwarded-For เพื่อปลอม IP ได้
      โชคดีที่ค่าเริ่มต้นปิดอยู่ แต่ก็ไม่มีคำเตือน
      เข้าใจว่าเป้าหมายคือความเรียบง่าย แต่ในสภาพปัจจุบันยังไม่พร้อม และมีตัวเลือกที่ดีกว่าเยอะจนไม่อยากใช้จริง
  • ยังไม่ค่อยเข้าใจว่าจะใช้สิ่งนี้อย่างไร และเหมือนผมอาจพลาดอะไรไป
    ตัวอย่างเริ่ม replica ของบริการ web 4 ตัว
    ถ้าสามารถ deploy ไปยัง replica หนึ่งตัว เช่น example-web-1 เพื่อสร้างบริการได้ แล้ว replica อีก 3 ตัวทำอะไรอยู่ก็ไม่รู้
    ถ้าจะอัปเดต web เพื่อ deploy แบบไม่หยุดให้บริการ น่าจะต้องรันคำสั่ง build บนบริการ web แล้วเริ่มบริการนี้ด้วยวิธีใดวิธีหนึ่ง จากนั้นค่อยรัน deploy ไปยัง target ใหม่
    แต่ถ้ารัน docker compose up --build --force-recreate web replica เดิมก็จะถูกปิดลง ทำให้ทั้งหมดไม่มีความหมาย

    • สำหรับคำถามแรก replica อื่น ๆ จะถูก Docker ทำ load balancing ด้วยวิธี VIP หรือคืนหลาย IP ในคำขอ DNS[0]
      ยังไม่ได้ตรวจว่าพร็อกซีนี้กระจายโหลดไปยังหลาย record ที่คืนจาก DNS request หรือไม่ แต่อย่างน้อยถ้าเป็น load balancing แบบ VIP ก็น่าจะทำงานตามที่คาดไว้
      ส่วนเรื่องอัปเดตข้อที่สองยังไม่ชัดเจนนัก
      อาจคาดหวังให้รันบริการชื่ออื่นใน network เดียวกันแล้วใช้ kamal-proxy deploy
      อาจเป็นแนวทางใส่เลขเวอร์ชันไว้ในชื่อบริการ และถ้าต้องการ rollback อย่างรวดเร็ว การคงเวอร์ชันก่อนหน้าไว้แบบพร้อมใช้งานก็สมเหตุสมผล
      [0]: https://docs.docker.com/reference/compose-file/deploy/#endpo...
    • ไม่รู้ว่าทำไมถึงไม่ใช้แค่ k8s rollout restart deployment
      หรือจะสลับ DNS หรือ router ระหว่าง backend สองตัวก็ได้
  • สงสัยว่านี่เป็นการทำแพตเทิร์น หยุดทราฟฟิกชั่วคราว หรือเปล่า
    เป็นวิธีที่พร็อกซีหยุดทราฟฟิกไว้จริง ๆ สักไม่กี่วินาที ทำให้ request ที่เข้ามาดูเหมือนใช้เวลานานกว่าปกติไม่กี่วินาที แต่เสร็จหลังหน่วงสั้น ๆ
    ในช่วงไม่กี่วินาทีนั้นสามารถรัน DB migration เล็ก ๆ หรือการเปลี่ยนแปลงโครงสร้างพื้นฐานแบบ blocking ที่ซับซ้อนขึ้นเล็กน้อยแต่จบได้ภายใน 5 วินาที

    • อยากรู้ว่ามีใครเคยทำแบบนี้ใน production จริงไหม
      ฟังดูค่อนข้างเสี่ยง และแม้จะเคยทำงานในบริษัทแอปเซิร์ฟเวอร์มาหลายปี แต่เพิ่งเคยได้ยินแพตเทิร์นนี้ครั้งแรก
      อย่างไรก็ตาม ถ้าเป็นผู้ร่วมก่อตั้ง Django ก็น่าจะเคยเห็นการ deploy มาเยอะ จึงยากจะมองข้ามไปเฉย ๆ
    • พูดตรง ๆ ฟังเหมือนแพตเทิร์น ใช้ชีวิตแบบเสี่ยง ๆ มากกว่า
    • Caddy ทำแบบนี้ได้
      จำได้ว่าเคยคุยกันเรื่องนี้มาก่อน
  • สงสัยว่ามีอธิบายไว้ที่ไหนว่าทำไมถึงเลือกสร้าง พร็อกซีของตัวเอง แทนที่จะใช้ Traefik หรือเครื่องมืออื่นที่พิสูจน์แล้ว

    • จริง ๆ ก่อนพรีรีลีส “v2.0.0” นี้ก็ใช้ Traefik อยู่
      ใน PR มีบริบทว่าทำไมถึงเปลี่ยนและทำเอง
      https://github.com/basecamp/kamal/pull/940
    • ผมพยายามสรุปเหตุผลไว้บ้างที่นี่ https://nts.strzibny.name/kamal-proxy/
      แต่ดูเหมือนจะไม่เคยมีการเปรียบเทียบกับตัวอื่นนอกจาก Traefik อย่างเป็นทางการ
  • สงสัยว่ามีวิธีตั้งค่า timeout ไหม
    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 ไม่มีอะไรจะเสริมแล้ว

    • กลับกัน ในดินแดนอันรุ่งโรจน์ของ “never invented here” ก็มีเรื่องแบบนี้เช่นกัน: https://news.ycombinator.com/item?id=38526780