Tuning Elasticsearch
ที่บริษัทใช้ ELK (Elasticsearch, Logstash, Kibana) ทำระบบ centralize log และผมกำลังสนใจว่าอยากจะใช้ Elasticsearch ในการทำ time-series สำหรับ monitor ระบบไปด้วย เลยขอลงมาดูรายละเอียดงานด้วยตัวเองบ้าง
อันดับแรกคือทำอย่างไรให้ระบบ centralize log มีความเร็วเพียงพอต่อการ ingest log เข้าไป และจากนั้นค่อยดูว่าทำอย่างไรให้ query log/aggregate log data ได้รวดเร็ว
ตัวเลข stats ปัจจุบันที่ ELK แสดงมีดังนี้
- 1,000,000 log lines in each minute (from Kibana)
- 100,000 average ingest rate per minute (from AWS)
- 9,200,000,000 searchable document (from AWS)
Elasticsearch cluster ที่ใช้
- AWS Elasticsearch
- 3 x c5.large.elasticsearch – master node
- 2 x i3.2xlarge – Hot data node
- 8 x ultrawarm1.medium.elasticsearch
Tuning for ingest
team setup cluster ไว้ว่าเมื่อจะ ingest document ให้ไปเขียนลงในเครื่อง hot data node ดังนั้นจะมี 2 เครื่อง i3.2xlarge คอย handle ตรงนี้ เราเริ่มเจอปัญหา log delay เพราะ ingest จาก logstash เข้า elasticsearch ไม่ทัน จึงเริ่ม tuning
เริ่มจากทดลองเปิด i3.2xlarge เพิ่มอีก 1 เครื่องรวมเป็น 3 เครื่อง ก็ดีขึ้น แต่ดูแนวโน้มแล้วถ้าจำนวน log เพิ่มน่าจะไม่ไหวอยู่ดี จึงหาวิธี tune เพิ่มเติม
ไปดูกราฟ cluster status ต่างๆ เจอว่า CPU hot data node แตะ 100% ตลอดเวลา
ลองปรับ type ของแต่ละ field ให้ใช้เป็น keyword แทน text เพื่อที่จะได้ไม่ต้องเสียเวลา analyze ตรงนี้ไม่ช่วยเท่าไร จากนั้นลองเช็ค config index template ดู set ไว้ตามนี้
- index.refresh_interval = 60s
- index.numberofreplicas = 0
- index.numberofshards = 6
ทีมลองปรับ logstash batch size จากเดิม 400 เป็น 800 อันนี้เห็นว่าดีขึ้น ตัว logstash queue size ลดลงเร็วกว่าเดิม แต่ยังไม่ชัดมาก ลองดันขึ้นเป็น 1600 ก็ไม่ค่อยต่าง และ CPU ของ data node ยัง 100% เสมอ
ลองลดเครื่อง data node ลงเหลือ 2 เครื่องเหมือนเดิม แล้วลอง tune
ไปเจอว่ามี translog setting ที่น่าจะเกี่ยว เดาว่าจะช่วยลดการ sync ข้อมูลลง disk จะช่วยให้ index เร็วขึ้น ลอง setting ตามนี้
- index.translog.durability = async
- index.translog.sync_interval = 1m
ซึ่งคิดว่าเรายอมเสีย log 1 นาทีได้ถ้าเครื่องมัน crash ไป
หลังจาก tune แล้ว performance ดีขึ้นเยอะมาก ไม่มี queue รอ ingest อีกต่อไป และ CPU ของ elasticsearch ก็ไม่เต็ม 100% ตลอดเวลาอีกแล้ว
Tuning for query
ผมมี plan ว่าอยากจะลองใช้ elasticsearch ทำ metric แบบ prometheus เพื่อประโยชน์ในเรื่องต่างๆ
- log กับ metric อยู่ใน storage เดียวกัน สามารถ query ร่วมกันได้
- aggregate จาก raw data โดยตรงได้ โดยที่ไม่โดน down sampling แบบ prometheus
- ถ้าเห็นว่า metric ตัวไหนมีปัญหา สามารถ query เจาดู raw data ได้ ซึ่ง prometheus ทำไม่ได้
- เอาไปทำ distributed tracing ได้
- สามารถ log metric อะไรลงไปก็ได้ผ่าน stdout โดยไม่ต้องทำ prometheus exporter
ผมยังทำ metric ไปไม่ถึงจุดนั้น แต่ก็อยากจะดูไว้ก่อนว่าจะเจอปัญหาอะไรบ้าง เพราะจำนวน log lines per minute มันเยอะมากๆ นาทีละ 1,000,000 line ถ้าอยากจะดู time-series ยาวๆ สัก 24 ชั่วโมง ก็คง hit 1,440,000,000 doc ที่ต้อง query + aggregate ซึ่งไม่รู้ว่ามันจะไหวจริงๆ หรือเปล่า
ไปเจอบทความนึงเขียนไว้ค่อนข้างละเอียดเรื่องการ tune elasticsearch เลยอยากเอามา share
Take away
elasticsearch สามารถ tune ได้เยอะมากๆ ในจุดต่างๆ แต่ที่สำคัญที่สุดคือเราต้องนึกให้ออกว่าแต่ละ request แต่ละ doc ที่ส่งไปให้ elasticsearch มัน index หรือ query มันเกิดอะไรขึ้นบ้าง ข้อมูลแต่ละ bit แต่ละ byte มันเดินทางผ่านอะไร ไปทางไหน แล้วไปลงที่ไหน ต้องเข้าใจพฤติกรรมของระบบให้ดี เข้าใจว่า OS ทำงานยังไง ทั้งหมดนี้คือต้องนั่งอ่านเยอะมากๆ
เมื่อเราเห็นเส้นทางของ data และเห็นวิธีการทำงานแล้ว เราจะนึกออกว่ามันช้าจุดไหน แล้วเราก็ค่อยไปหาว่ามันมีปุ่มหรือ setting ให้ tune หรือไม่ แล้วก็ลอง tune ดู