Trino on k8s
หมายเหตุ ผู้อ่านสามารถดู table of contents ของ Data Engineering from Noob to Newbie ได้ที่ http://bit.ly/2P7isEw
หากจะพูดถึง software ที่ถูกใช้เป็น query engine เพื่อที่จะ query ข้อมูลจากหลายๆ data source ได้จากจุดเดียว เช่น query ข้อมูลในรูปแบบ parquet file บน aws s3 มา join กับข้อมูลที่อยู่ใน postgresql ที่ติดตั้งใน on premise แล้ว insert ผลลัพธ์จากการ join เก็บใน aws redshift ซึ่ง software ในกลุ่มนี้หลายๆท่านน่าจะนึกถึง Presto ซึ่งเป็น engine ที่อยู่เบื้องหลัง aws athena แต่หลังจากเข้ามามีส่วนร่วมของ Facebook ทำให้ทีมพัฒนา Presto เดิมแยกออกทำ project ใหม่ภายใต้ชื่อ PrestoSQL และเปลี่ยนชื่อมาเป็น Trino ในเวลาต่อมา ซึ่งบทความนี้เราจะมาดูการทำงานของ Trino เบื้องต้นร่วมถึงการติดตั้ง Trino บน kubernetes
ท่านสามารถอ่านข้อมูลเพิ่มเติมการแยก project ได้จาก
Trino เบื้องต้นฉบับเร่งด่วน
- Coordinator ทำหน้าที่รับ sql จาก client แล้วทำการวิเคราะห์และวางลำดับการประมวลผล เพื่อสั่งงาน worker ให้ดำเนินการ ซึ่ง Coordinator และ Worker จะสื่อสารกันโดยใช้ REST api บน HTTP/HTTPS protocol
- Worker ทำหน้าที่รับคำสั่งการประมวลที่ Coordinator ออกแบบไว้ ซึ่งภายในขบวนการทำงานจะมีการแบ่งกลุ่มลำดับการทำงานออกเป็น stage โดยจากรูปข้างต้นสามารถแบ่ง stage ออกได้คราวๆ 2 stages ซึ่งเริ่มจาก stage 0 ใช้ 2 workers อ่านข้อมูลจาก data source ผ่านทาง Connector และอาจะมีการประมวลภายใน stage 0 ก่อนส่งต่อผลลัพธ์ให้กับ stage 1 ที่มี 1 worker ทำหน้าที่รวบรวมผลลัพธ์จาก 2 workers และประมวลผลขั้นตอนสุดท้าย เพื่อให้ได้ผลลัพธ์ที่ client ต้องการและส่งผลลัพธ์ดังกล่าวกลับไปยัง Coordinator เพื่อส่งต่อให้กับ client ในลำดับถัดไป
ข้อมูลภายใน Trino จะแบ่งออกได้เป็น 3 ระดับใหญ่ๆคือ
- Catalog เป็นตัวเก็บข้อมูลการเชื่อมต่อจาก Trino ไปยัง data source ผ่านทาง connector โดยแต่ละ catalog จะเกิดจาก property file ที่อยู่ใน catalogs ภายใน Trino cluster ซึ่งชื่อของ catalog จะอ้างถึงชื่อ file ของ property นั้นเอง
- Schema จะอยู่ภายใต้ catalog ทำหน้าที่จัดเก็บ table เสมือน schema ใน rdbms
- Table คือตารางจัดเก็บข้อมูลที่ user จะทำการ query
Memory ภายใน Trino
เพื่อทำความเข้าใจเกี่ยวกับ memory ภายใน trino เรามาเริ่มจาก memory ระดับ node กันก่อนนะครับ โดย trino จะใช้งาน memory ภายใน jvm heap ของแต่ละ node ซึ่งประเภทของ memory ที่ trino ดูแลจะมีอยู่ด้วยกัน 2 ตัวคือ
- user memory ใช้สำหรับเก็บของข้อมูลระหว่างที่ user ทำการ query
- system memory เป็น memory ใช้เพื่อการทำงานของตัว trino เอง
แต่ยังมี memory อีกหนึ่งตัวที่สำคัญในการ tuning แต่ Trino ไม่ได้เป็นคนจัดการโดยตรงนั้นคือ headroom/buffer ภายใน jvm ซึ่งในแต่ละ node เราจำเป็นต้อง balance ตัว memory ทั้ง 3 ให้ดี
ถัดมาเป็น memory ในระดับ cluster ซึ่งเกิดจากการรวบรวม memory ของแต่ละ node โดยในระดับ cluster นี้จะมี user memory และ system memory เท่านั้น
ในการ config memory ภายใน trino เราไม่สามารถกำหนด system memory ได้ตรงๆ ที่เราสามารถกำหนดได้มีเพียงจำนวน memory ที่เราจะกำหนดเป็น user memory และ total memory ซึ่งเกิดจาก user memory + system memory นั้นเอง ตัวอย่างเช่นเราบอกว่า total memory ในแต่ละ node จะให้อยู่ 8GB แต่ user memory เราจะให้อยู่ 6GB ทำให้อีก 2GB ที่เหลือจะถูกใช้สำหรับ system memory นั้นเอง เช่นเดียวกับระดับ cluster ที่เราก็สามารถกำหนด max user memory ใน cluster และ max total memory ใน cluster ได้เท่านั้น
การติดตั้ง Trino
เราสามารถติดตั้ง Trino บน k8s ได้ง่ายๆโดยการใช้งาน helm chart ที่ทาง Trino จัดเตรียมไว้ให้ใน https://github.com/trinodb/charts ซึ่งขั้นแรกเราจะทำการ load repo
git clone https://github.com/trinodb/chartscd ./charts/charts/trino
จากนั้นเราจะมาดูแต่ละ session ที่เราจะสามารถ custom ค่าต่างๆของ Trino clusterใน values.yaml ได้เริ่มจาก
Image session เป็นส่วนที่เราสามารถระบุ version ของ trino image จาก docker hub ซึ่งถ้า default จะเป็น lastest
ในส่วนของ server detail จะเริ่มจาก
workers session ใช้ระบุจำนวนของ worker ซึ่งจากรูปเราจะทำการสร้าง cluster ที่ประกอบไปด้วย 2 worker nodes
node session ใช้ config ข้อมูลของแต่ละ node ใน cluster โดย config ดังกล่าวจะถูกนำไปสร้างเป็น file ที่ชื่อ node.properties ภายใน node ซึ่ง config หลักใน session นี้จะเป็น dataDir ที่ใช้ระบุ path ที่ Trino จะใช้เก็บ log และ data
log session ใช้ระบุ level ของ log ที่ trino จะแสดงออกมายัง file log โดย config ดังกล่าวจะถูกนำไปสร้าง file ชื่อ log.properties
config.path session ระบุ location ของ Trino ซึ่งโดย default ถ้าเราใช้ official Trino image ตัว location ที่เก็บ Trino จะเป็น /etc/trino
config.query และ config.memory session เป็นพื้นที่ config ที่เราสามารถ tuning memory ภายใน Trino cluster ได้ ตามที่เราได้ทำความเข้าใจเกี่ยวกับ memory ใน trino กันไปแล้วก่อนหน้านี้ ซึ่งจาก templates ของ chart ในส่วนนี้ตามรูปด้านล่าง
เราจะเห็นได้ว่าค่าของ memory ที่เราสามารถระบุได้ใน session นี้มีอยู่ด้วยกัน 4 ค่าด้วยกันคือ
- max-memory: user memory ใน cluster
- max-memory-per-node: user memory ในแต่ละ node
- max-total-memory-per-node: total trino memory ซึ่งเกิดจาก user memory + system memoryในแต่ละ node
- heap-headroom-per-node: headroom/buffer ใน jvm ของแต่ละ node
ส่วน max-total-memory นั้นหากท่านต้องการ config เพิ่ม สามารถทำได้โดยการเพิ่มเข้าไปในส่วนของ additionalConfigProperties session
jvm session เป็นส่วนหลักในการระบุ jvm heap ของแต่ละ node
จากรูปข้างต้นเป็นส่วนที่ให้เราสามารถ config ค่าในแต่ละกลุ่มเพิ่มเติม ซึ่งเราจะใช้ในกรณีที่ template ของ chart ไม่มีการระบุค่านั้นไว้เช่น ใน template ของ config.properties ที่เราได้เห็นด้านบน ไม่มีการระบุคือ config เกี่ยวกับ splilling หากเราต้องการเปิดใช้งานต้องมากำหนดในส่วนของ additionalConfigProperties เพิ่มเติม
อีกส่วนนึงที่มีความสำคัญในการใช้ deploy Trino บน k8s คือ node selector โดยเราสามารถกำหนดได้ใน nodeSelector session
หลังจากที่เรากำหนดค่า config ต่างๆใน vlaues.yaml เรียบร้อยแล้วก็ทำการ deploy ผ่านทาง helm install ได้เลย
helm install -f values.yaml trinodb . -n trino
เพื่อทำการตรวจสอบเบื้องต้นเราจะทำ port forward ตัว trino service โดยใช้ kubefwd
sudo kubefwd svc -n trino
ซึ่งเมื่อใช้คำสั่งด้านบนจำทำให้เราสามารถ trinodb:8080 ผ่านทาง web browser ได้ (หากบนหน้าจอให้ใส่ username เราสามารถใส่อะไรก็ได้ในตอนนั้นเพราะยังไม่มีการตั้งค่า authentication)
โดย default แล้ว trino chart จะมี catalogs มาให้เรา 2 ตัวนั้นคือ tpch catalog และ tpcds catalog (https://github.com/trinodb/charts/blob/main/charts/trino/templates/configmap-catalog.yaml) ซึ่งเราสามารถใช้ sql client อย่าง dbeaver เชื่อมต่อเพื่อ query 2 catalogs ดังกล่าวได้เลย โดยเฉพาะ dbeaver ซึ่งมี connector Trino มาให้เราแล้ว
ถึงตรงนี้การติดตั้ง Trino cluster บน k8s เบื้องต้นของเราก็เสร็จสมบูรณ์ ในบทความต่อไปเราจะมาดูการ สร้าง hive catalog เพื่อ query ข้อมูลใน parquet file บน aws s3 กันนะครับ
สุดท้ายนี้ถ้าท่านใดมีข้อสงสัยหรือคำชี้แนะใดๆสามารถฝากข้อความได้ที่ https://www.facebook.com/coeffest/ นะครับ ขอบคุณมากครับที่ติดตาม
สำหรับคนที่สนใจ Data Engineer สามารถเข้ามาแชร์ข้อมูลกันที่ได้ที่ https://www.facebook.com/groups/369157183664760/