AWS Thai Blog
ขยายจำนวน pod จากหลักร้อยไปหลักหมื่นบน Amazon EKS คลัสเตอร์
บทความนี้แปลมาจาก Scale from 100 to 10,000 pods on Amazon EKS ที่เขียนร่วมโดย Nikhil Sharma และ Ravishen Jain จาก OLX Autos กับ Akshaya Rawat จาก AWS
บทนำ
OLX Autos ทำการสร้างระบบสำหรับทีมนักพัฒนาภายในให้ใช้กันที่มีชื่อว่า ORION โดยระบบ ORION นั้นเป็นระบบที่มีไว้ใช้สร้างและรัน application สำหรับ non-prod environment ซึ่งระบบรองรับมากกว่า 100 environment ในช่วงเวลาเดียวกัน เพื่อที่ใช้ในการทดสอบ use case ที่แตกต่างกัน โดยในแต่ละ environment จะมีจำนวน pod ที่รันมากกว่า 100 ตัว ด้วย Amazon Elastic Kubernetes Service (Amazon EKS) จุดประสงค์ที่มีการสร้าง environment ขึ้นมามากมายนั้นก็เพื่อให้นักพัฒนาสามารถทำการทดสอบ feature ใหม่ๆ ได้พร้อมกัน ส่วน environment ที่ไม่ได้ใช้งานแล้วก็จะถูกทำลายทิ้ง ซึ่งทางทีมวิศวกรของ OLX Autos เลยตัดสินใจ ใช้ Amazon EKS เพียงแค่ 1 คลัสเตอร์ ในการโฮส environment ทั้งหมด เพื่อที่จะสามารถใช้ทรัพยากรให้มีประสิทธิภาพดีขึ้น พวกเขายังเลือกใช้ spot อินสแตนซ์ สำหรับ Amazon EKS เพื่อช่วยประหยัดค่าใช้จ่ายลงได้อย่างมาก ในบางช่วงเวลาระบบ ORION นั้นต้องรองรับจำนวน pod มากกว่า 10,000 ตัว ที่รันอยู่บนคลัสเตอร์เดียวกัน แถมยังต้องรองรับการสร้าง environment ใหม่ๆ ตามความต้องการของทีมนักพัฒนาอีกด้วย
ในบทความนี้ ทางทีมวิศวกรของ OLX Autos ได้อธิบายว่าพวกเขาเจออุปสรรคอะไรบ้างและแก้ปัญหาอย่างไรจึงสามารถขยายจำนวน pod ที่รันบน Amazon EKS คลัสเตอร์ จาก 100 ไปจนมากกว่า 10,000 ตัวได้
ก่อนอื่นมาทำความรู้จักกับ OLX Autos
OLX Autos เป็นบริษัทลูกของ OLX Group ทำระบบซื้อขายยานพาหนะมือสองและขยายธุรกิจไปในหลายประเทศ จุดเด่นของแพลตฟอร์มคือเป็นระบบที่ช่วยสร้างความมั่นใจ สะดวก และทำธุรกรรมจบในที่เดียวทั้งสำหรับผู้ซื้อและผู้ขาย OLX Autos จัดเป็นบริษัทที่ทำการปฏิรูปวงการซื้อขายรถยนต์มือสอง โดยรวมประสบการณ์การซื้อขายรถยนต์มือสองผ่านทางออน์ไลน์และออฟไลน์เข้าด้วยกัน ซึ่งปัจจุบัน OLX Autos ก็ขยายธุรกิจไปถึง 11 ประเทศแล้ว
อะไรคือ OLX Autos IDP – Orion
ทีมวิศวกรของ OLX Autos ได้ทำการสร้าง environment ที่ชื่อว่า Roadster ไว้สำหรับโฮส application สำหรับธุรกิจในหลายภาคส่วน อย่างเช่น ซื้อขายรถยนต์ การเงิน และการตรวจสอบ โดย environment ที่ใช้ต้องมีคุณสมบัติที่ทำงานได้เร็ว สามารถแตกเป็นโมดูลย่อยๆได้ และระบบสามารถฟื้นกลับมาทำงานใหม่ได้เมื่อระบบผิดปกติ รวมถึงเลือกใช้เทคโนโลยีที่มีความล้ำสมัย เพื่อช่วยให้ OLX Autos ยังเป็นผู้นำในตลาดซื้อขายรถยนต์มือสอง ซึ่งมีการแข่งขันกันที่ดุเดือนเป็นปกติอยู่แล้ว ท้ายสุดทีมวิศวกรได้เลือก Amazon EKS มาใช้งานในการโฮส Roadster environment เพราะสามารถตอบโจทย์คุณสมบัติตามที่ต้องการได้ตามที่กล่าวมา
เนื่องจาก OLX Autos ทำการขยายฐานลูกค้าสม่ำเสมอ ทำให้การส่งมอบ feature ใหม่ๆให้ทันหรือก่อนคู่แข่งนั้น ถือเป็นความท้าทายที่สำคัญ เพราะฉะนั้นการช่วยลดความซับซ้อน และเพิ่มประสิทธิภาพการทำงานของทีมนักพัฒนา เป็นเป้าหมายหลักของทีมวิศวกรที่ดูแล Roadster environment ตามที่ได้กล่าวมาก่อนหน้านี้ทีมวิศวกรต้องสร้าง Roadster ขึ้นมาหลายๆ environment สำหรับใช้ทดสอบ use case ต่างๆ รวมทั้งการทำ automated test สำหรับการทดสอบในตลาดลูกค้าใหม่ๆ โดยในหนึ่ง Roadster environment จะประกอบไปด้วยหลากหลาย micro service รวมถึงฐานข้อมูล ซึ่งต้องทำงานควบคู่กันในแต่ละ use case
เป็นที่ทราบกันดีว่าการสร้างและดูแล Roadster environment เป็นงานที่ต้องใช้เวลาและทรัพยากรมาก ทางทีมวิศวกรจึงสร้างระบบ Internal Developer Platform (IDP) หรือ Orion ขึ้นมาเพื่อเป็น platform ตัวกลางเพื่ออำนวยความสะดวกในการสร้าง Roadster environment ให้แต่ละทีมที่ใช้งาน
Solution overview
แผนภาพด้านล่างแสดง architecture ของระบบ Orion
โดยระบบ Orion ถูกออกแบบมาเพื่อที่จะ
- ลดความซับซ้อนของทีมนักพัฒนา โดยรวบรวมแต่ละ service กับเครื่องมือต่างๆ ให้สามารถเข้าถึงและใช้งานได้อย่างราบรื่น
- ช่วยทีมนักพัฒนาสามารถสร้าง Roadster environment ขึ้นมาได้เองโดยที่ไม่ต้องพึ่งทีมงานที่ดูแล โดยสามารถสร้าง Roadster environment ผ่านการคลิ๊กเพียงแค่ไม่กี่ครั้ง
Amazon EKS ถูกเลือกมาใช้ในการรันระบบ IDP (Orion)
ใน Roadster environment นั้น application เป็น container ทั้งหมดและรันบน Amazon EKS มานานนับปี ซึ่ง Amazon EKS ก็เป็นตัวเลือกที่ตอบโจทย์สำหรับ Orion ในการนำมาใช้สร้าง Roadster environment ที่มีมากกว่า 100 environment โดยใช้ Amazon EKS เพียงคลัสเดียวในการโฮส environment ทั้งหมด
จากภาพด้านล่างแสดงให้เห็นจำนวนทรัพยากรที่ Orion ดูแลและจัดการบน Amazon EKS คลัสเตอร์
อย่างไรก็ดี ตามที่ระบบ ORION เริ่มถูกใช้งานมากขึ้น ทางทีมก็เริ่มเจออุปสรรคต่างๆ จากการรัน Roadster environment ที่มีจำนวนมากขึ้น
ทางทีมของ OLX Autos เลยถือโอกาสแบ่งปันข้อมูลเกี่ยวปัญหาที่พบเจอและแนวทางการแก้ไข ดังต่อไปนี้
ปัญหา latency ที่สูงขึ้นของ DNS resolution
ปัญหาแรกที่เจอคือเรื่อง classic ndots โดยปกติค่าตั้งต้นของ ndot คือ 5 ที่ถูกเซ็ตไว้ใน Amazon EKS ตามมาตรฐาน DNS โดเมนเนมจะถูกมองเป็น FQDN ถ้าจำนวน dot(.) เท่ากับค่าของ ndot หรือโดเมนเนมที่มี dot ปิดท้าย ในกรณีที่คิวรี DNS ของโดเมนเนมที่ไม่มี dot ปิดท้าย core-dns จะต้องทำการวนหาทุกโดเมนเนมที่เป็นไปได้จนกว่าจะครบหรือสำเร็จ
ยกตัวอย่างเช่น ถ้าทำการคิวรี amazon.com จากบน pod core-dns จะทำการคิวรีโดเมนเนมดังต่อไปนี้
โดยเรียงเป็นลำดับ หรือจนกว่าจะได้ผลลัพธ์ที่สำเร็จ
ทางทีมวิศวกรของ ORION ได้ทำการทดสอบ nslookup ด้วย amazon.com บน worker node ของ Amazon EKS คลัสเตอร์ ผลที่ได้คือมีการยิง DNS question ไป 7 ครั้งโดย 5 ไม่ได้คำตอบ และอีก 2 ครั้งได้กลับมาเป็นของ IPv4 กับ IPv6
จากสกรีนช็อตด้านล่างแสดงผลลัพธ์ที่ได้จากการรันคำสั่ง nslookup กับ amazon.com และทำการนับจำนวนการคิวรี DNS และ error ที่เกิดขึ้นจากการคิวรี DNS โดยใช้คำสั่ง grep QUESTIONS และ grep NXDOMAIN ตามลำดับ
เนื่องจากระบบ Orion มีขนาดใหญ่ขึ้น การคุยข้าม service กันก็มีมากขึ้นตาม ส่งผลให้จำนวนการคิวรี DNS ก็ถี่ขึ้นตาม ถ้าค่าคอนฟิคของ ndot คือ 5 ก็จะทำให้มีการคิวรีเพิ่มขึ้น 5 เท่า และผลกระทบที่ตามมาก็คือ core-dns นั้น crashed และทำให้พบ error จากการแปลงโดเมนเนมเป็นไอพีแอดเดรสบ่อยครั้ง ถ้าสนใจเพิ่มเติม สามารถศึกษาเกี่ยวกับผลกระทบที่เกิดจาก ndot บน Kubernetes เพิ่มเติมได้จากบทความนี้
Response time สูงขึ้นเนื่องจาก CPU throttling
โดยเริ่มแรกทางทีมวิศวกรของ OLX Autos ทำการกำหนดค่า CPU limit ของ pod ซึ่ง CPU Limit เป็นตัวกำหนดว่า container สามารถใช้ CPU time ได้เท่าไร และการที่กำหนดค่า CPU limit ยิ่งทำให้ปัญหาเรื่อง ndot แย่ลงเข้าไปใหญ่ จากที่ได้กล่าวมาก่อนหน้านี้ทุกการคิวรี DNS มีโอกาสจะไม่ได้ผลลัพธ์ก่อนที่จะได้ครั้งที่สำเร็จ และ CPU limit ดันไปควบคุมจำนวนของ CPU time ทำให้ container อาจต้องรอโอกาสของ CPU cycle ในรอบถัดๆ ไป ในการทำวนคิวรี DNS ซ้ำจนกว่าจะสำเร็จ ถ้ากลไกดังกล่าวเกิดขึ้นซ้ำๆ บ่อยครั้งส่งผลให้ application มีประสิทธิภาพที่แย่ลงรวมถึง latency ที่สูงขึ้นด้วย ทางทีมวิศวกรเลยทำการแก้ไขค่า CPU limit กลับไปเป็นค่าตั้งต้น โดย Eric Kuhn ได้ทำการอธิบายเกี่ยวกับผลกระทบจากการตั้งค่า CPU limit ไว้ในบทความนี้
แนวทางการแก้ปัญหา ndot โดยเพิ่ม dot ไปที่ท้ายของโดเมนเนม
การที่ต่อท้าย dot ไปที่โดเมนเนม ทำให้โดเมนเนมถูกมองเป็น FQDN ส่งผลให้ตอนทำการคิวรี DNS จะไม่วนหาไอพีแอดเดรสจาก search path ซึ่งช่วยให้ลดจำนวนการคิวรี DNS ลง
ทีมงานได้ทำการทดสอบรันคำสั่ง nslookup ด้วย amazon.com ผลที่ได้ปรากฏว่าจำนวน DNS question ลดจาก 7 มาเหลือแค่ 2 ครั้งและไม่มี error จาก NXDOMAIN เลย ซึ่งวิธีนี้ช่วยลดจำนวนคิวรีที่เกิดขึ้นแก่ core-dns ได้มากกว่า 70%
จากสกรีนช็อตด้านล่างแสดงให้เห็นผลลัพธ์จากการรันคำสั่ง nslookup ด้วย amazon.com.
โดยทางทีมได้เพิ่ม dot ต่อท้ายเข้าไปกับ http endpoint ของแต่ละ service ผ่านการตั้งค่าให้กับ environment variable
ทำ DNS cache เพื่อลด latency ลงได้อีก
ระบบ Orion นั้นมีสเกลที่ใหญ่ การเพิ่ม dot ต่อท้ายโดเมนเนมนั้นยังไม่สามารถแก้ปัญหา latency ที่สูงได้หมดไป ทีมวิศวกรของ OLX ได้ประยุกต์ใช้ NodeLocal DNSCache agent ที่พัฒนาโดยคอมมูนิตี้ของ K8S เอง การนำ feature นี้มาใช้ช่วยให้ application ทำงานได้เร็วขึ้น
จากภาพด้านล่างแสดงให้เห็น response time ระหว่างใช้กับไม่ใช้คุณสมบัตินี้
ปัญหาการขาดแคลนของ IP กับการใช้งาน VPC CNI ปลั๊กอิน
สำหรับ VPC CNI ปลั๊กอิน ถูกรันในรูปแบบ daemonset โดยมีหน้าที่ในการจัดหาไอพีแอดเดรสที่ว่างใน Amazon VPC ให้แก่ pod โดยแรกเริ่ม VPC CNI จะทำการเพิ่ม ENI อีกหนึ่งตัวให้กับ worker node เป็นทั้งหมด 2 ตัว และทำการจองไอพีแอดเดรสจำนวนหนึ่งไว้ด้วย
ซึ่งจำนวนของไอพีแอดเดรสที่ใช้ได้ ขึ้นอยู่กับ instance type ของเครื่อง ซึ่งสามารถเช็คเพิ่มเติมได้ว่า instance type แต่ละประเภทสามารถรองรับจำนวน ENI ได้เท่าไรต่อเครื่อง และในหนึ่ง ENI สามารถรองรับจำนวนไอพีแอดเดรสได้เท่าไรจากเอกสารนี้
เพราะฉะนั้นเราสามารถตีความได้ว่า เครื่องที่มี instance type เป็น c5.9xlarge จะทำการจองไอพีแอดเดรสอยู่ที่ 58 ไอพี (29 ไอพีต่อ 1 ENI) จาก VPC pool ถึงแม้จะไม่มี pod รันอยู่บนเครื่องนั้นๆ ก็ตาม
ซึ่งผลกระทบที่เกิดขึ้นก็คือไอพีแอดเดรสจะเกิดการขาดแคลนใน VPC และ Amazon EKS คลัสเตอร์จะไม่สามารถเพิ่มเครื่องเข้ามาใหม่ได้ รวมถึง AWS resources อื่นๆใน VPC เดียวกันก็ไม่สามารถถูกสร้างได้เช่นกัน
อย่างไรก็ตาม เราสามารถตั้งค่าจำนวนไอพีและ ENI ที่ถูกจองโดย VPC CNI ปลั๊กอิน ผ่าน parameter ของปลั๊กอินได้ดังต่อไปนี้
– MINIMUM_IP_TARGET คือจำนวนขั้นต่ำที่ไอพีจะถูกจองไว้ให้แต่ละเครื่อง
– WARM_IP_TARGET คือจำนวนสูงสุดของไอพีที่จองไว้ได้แม้ยังไม่ได้ถูกใช้งานของแต่ละเครื่อง
– WARM_ENI_TARGET คือจำนวน ENI ที่สามารถผูกกับเครื่องได้
อันดับแรกใช้ WARM_IP_TARGET เพื่อลดจำนวนไอพีที่ถูกจองไว้แต่ยังไม่ใช้งานลง
เริ่มแรก ทางทีมงานตั้งค่า WARM_IP_TARGET = 1 ซึ่งจะทำให้มีแค่ไอพีเดียวที่ถูกจองไว้
โดยสามารถรันคำสั่งตามด้านล่าง เพื่อตรวจสอบจำนวนไอพีที่ถูกใช้งานและถูกจองไว้บนเครื่องนั้นๆ
จากรูปแสดงผลลัพธ์ของคำสั่งที่รันด้านบน
จากการตั้งค่าของก่อนหน้า ช่วยแก้ปัญหาไอพีขาดแคลนได้จริง แต่กลับก่อให้เกิดอีกปัญหาหนึ่งแทน เนื่องจากมีแค่หนึ่งไอพีที่ถูกสำรองไว้ (WARM_IP_TARGET=1) เมื่อไรก็ตามที่มี pod จำนวนมากถูกสร้างขึ้น จำนวนไอพีก็จะถูกขอใช้เป็นจำนวนมากเช่นกัน ส่งผลให้เกิดสถานการณ์การแย่งไอพีกัน ทำให้ pod ต้องรอ VPC CNI ปลั๊กอินทำการแจกจ่ายไอพีแอดเดรสให้ worker node ก่อน ในจังหวะนี้ error ที่ทางทีมเจอคือ ‘failed to assign an IP address to container and DataStore has no available IP addresses’ (ไม่สามารถกำหนดไอพีให้แก่ container ได้ เพราะไม่มีไอพีแอดเดรสเหลืออยู่)
โดยสามารถเช็ค error event ได้จากคำสั่ง kubectl describe pod <pod_name>
หรือจากไฟล์ log ที่ /var/log/aws-routed-eni/ipamd.log ของ worker node