Skip to content

บันทึกสิ่งที่ได้เรียนรู้จากการใช้งาน AWS Elasticsearch service

งานที่ผมทำอยู่ตอนนี้ใช้งาน Apache Kafka เป็น distributed messaging และใช้ Elasticsearch เป็น storage เก็บข้อมูลและค้นคืนในการทำ analytics ซึ่งก็เจอแง่มุมที่น่าสนใจ สิ่งที่ต้องคำนึงถึงในการใช้งาน Elasitcsearch หลายอย่าง เลยอยากแชร์สิ่งที่พบเจอระหว่างทางซะหน่อย

Elasticsearch ที่ผมจะกล่าวถึงต่อไปนี้คือ Elasticsearch service บน AWS ต่อไปนี้ผมจะเรียก Elasticsearch ว่า ES ละกันเพื่อความกระชับ ส่วนหัวข้อที่จะเขียนแยกเป็น 2 ส่วนคือ ES topology  และการ ES tuning/troubleshooting เพื่อรองรับงานที่เน้น write operation เป็นหลัก

Elasticsearch topology

ส่วนนี้เป็นการ design  system เราครับ ต้องตัดสินใจว่า topology ของ ES ควรมีกี่ master node กี่ data node ต้องการทำ fault tolerance และใช้งาน AZ (Availability Zone) หรือไม่ ระบบที่ผมใช้งานตอนนี้ประกอบด้วย

  • 3 Master nodes เป็น fault tolerance
  • 6 Data nodes แต่ละ node จะมีขนาด storage  จำนวนหนึ่งซึ่งผลรวม capacity ของ storage  แต่ละตัวคือ capacity ที่ ES สามารถเก็บข้อมูลได้
  • Indices rolling ตามวันที่ แต่ละ indice มี 5 Shards และใช้แค่ 1 replica เท่านั้น

ทีนี้มาดูเหตุผลว่าทำไมต้องใช้ตัวเลขตามข้างบนกัน

  • 3 Master nodes เป็นจำนวน node  น้อยที่สุดของระบบที่เป็น fault tolerance เป็น practice หนึ่งที่จำนวน node มักจะเป็นเลขคี่ตั้งแต่ 3  ขึ้นไป เช่นอาจจะเป็น 3, 5, 7, 9 เป็นต้น การทำงานของ fault tolerance จะต่างจาก cluster ตรงที่หลาย node ไม่ได้ทำงานร่วมกันแต่จะมี Master node ทำงาน ณ ขณะนั้นเพียงตัวเดียวเรียกว่า leader ส่วนที่เหลือจะ standby รอทำงาน หาก leader พังทำงานไม่ได้ Master node ตัวที่เหลือก็จะถูก assign ให้เป็น leader มาทำงานแทน
    Instance type สำหรับ Master nodes ใช้เป็น t2.small.elasticsearch ก็พอเพราะไม่ได้รับ load อะไรมาก
  • 6 Data nodes เป็นเลขคู่เนื่องจากเป็นข้อกำหนดของ AWS ES ว่าถ้าใช้งาน AZ ตอนนี้ region ที่ Singapore มี 3 zones (3 data centers) คือ -a, -b, -c ก็จริงแต่ AWS ES ยังใช้ได้แค่ 2 zones คือ -a, -b เท่านั้นจึงทำให้ตัวเลขที่ใช้เป็นเลขคู่เพราะ Data node จะกระจายอยู่แต่ละโซนอย่างละครึ่ง เช่นกรณีนี้จะอยู่ -a zone 3 Data nodes และ -b zone 3 Data nodes
    เดิมทีทีมผมใช้ 4 nodes แต่ในช่วง peak time load ขึ้นสูงทำให้ messages ที่ Kafka lag เลยต้องเพิ่มเป็น 6
    Instance type สำหรับ Data nodes ผมเลือกใช้ default m4.large.elasticsearch เพราะตอนนี้ปริมาณข้อมูลที่มีอยู่ ใช้ type นี้ก็รับได้สบายๆ
  • เหตุผลที่ rolling indice ตามวันเนื่องจากไม่อยากให้ indice ขนาดใหญ่เกินไปและเพื่อให้ลบ indice  เก่าตามวันได้ง่ายๆ จำนวน shard ใช้ค่า default ของ ES คือ 5 shard ซึ่งกำหนดได้ครั้งแรกตอนสร้าง indice และจะแก้ไขทีหลังไม่ได้ต้องลบแล้วสร้างใหม่อย่างเดียวจึงไม่อยากแตะอะไรมาก
    Replica เลือกใช้น้อยเพราะทดลองแล้วว่าการใช้จำนวนเยอะๆ ทำให้ messages lag เพราะการกระจาย messages ให้ครบทุก replicas มี overhead และยิ่งใช้จำนวน replica มากก็ใช้ storage มากขึ้นเป็นไปด้วยเพราะเป็นการ copy ข้อมูลเดียวกันหลาย ๆ ชุด จำนวน replica สามารถปรับได้ตลอดเวลาผ่าน /_settings API

ปัญหาที่พบและวิธีแก้ไข (Troubleshooting)

Write operation ช้ามาก

เมื่อปล่อยให้ระบบทำงานไปได้สักพักปรากฏว่า messages lag เยอะมากและบางครั้ง Kafka connect ก็ error และหยุดการทำงานเนื่องจาก ES ใช้เวลาในการ flush ข้อมูลนานเกินไปจน timeout ซึ่งอาจจะเกิดได้หลายสาเหตุ

  • Disk storage  ใกล้เต็ม หากพบว่า disk ใกล้เต็มให้ทำงานเพิ่ม volume EBS ของ Data nodes ใน document ของ ES บอกว่าหาก ES พบว่ามีการใช้ disk ไปประมาณ 85% ก็จะ mark ไว้ว่า low resource เพราะฉะนั้นควรมี monitoring แจ้งเตือนไม่ให้เกินค่านี้
  • หากเช็ก Disk storage แล้วพบว่ายังเหลืออยู่เยอะให้ทำงานปรับลดจำนวน replica ลงเป็นจำนวนน้อย ๆ หรือ เป็น 0 ไปเลยจะช่วยให้ write operation ทำได้เร็วขึ้นเพราะไม่ต้องกระจาย message ไปหลาย replica โดยปรับ index.number_of_replica: “0” หาก messages ไม่ lag แล้วค่อยปรับคืนเป็นค่าเดิมที่เคยใช้ (ของผมปรับเป็น 1)
  • เนื่องจาก ES ต้องการทำ Near real-time search คือต้องการให้ข้อมูลที่ทำ index สามารถค้นหาเจอได้แทบจะทันทีทำให้ค่า default ในการ refresh index ถูกตั้งไว้ที่ 1 วินาทีซึ่งมีผลต่อการเขียนข้อมูลค่อนข้างมาก หากงานของเราไม่ต้องการใช้ฟีเจอร์ Near real-time search ให้ปรับ refresh interval ให้มากขึ้น เช่น   index.refresh_interval: “300s” เพื่อให้ refresh index ทุก 300 วินาทีหรือ 5 นาที

Load ของ Data node ขึ้นสูง

บางครั้งผมก็เจอว่าอยู่ดีๆ load ของ Data node บางตัวก็ขึ้นสูงโดยไม่ทราบสาเหตุทั้งที่ไม่ใช่ช่วง peak time หากเรามี Data node เพียงพอแล้วแต่ load ก็ยังไม่ลดลงสักทีให้ทำการ scale up Data node ขึ้น (เพิ่มจำนวน Data node) เสร็จแล้วให้ scale down ลงเป็นจำนวนเท่าเดิมเพื่อให้ AWS ES สร้าง instance ใหม่มาแทน instance เดิม

จริงๆ วิธีนี้ก็เป็น practice หนึ่งของการใช้งาน  cloud server คือควรจะ rolling instance ของ application (สร้าง instance ใหม่มาแทน instance เดิม) เพื่อ reset resource ให้เป็นของใหม่อยู่เสมอเนื่องจากบางครั้ง application ที่เราเขียนก็มีปัญหา memory leak บางทีตัว garbage collector ก็จัดการได้ไม่หมด อย่างไรก็แล้วแต่การ rolling นี้จะใช้ได้ก็ต่อเมื่อระบบถูกออกแบบมาให้ขยายออกทางด้านข้างหรือ Horizontal scaling คือเพิ่มจำนวน node เพื่อรับ load ที่มากขึ้น node ใดตายไปก็ไม่ส่งผลต่อระแบบโดยรวม หากไม่ได้ออกแบบ application ไว้แบบนี้แต่แรกก็ไม่ควรทำครับเพราะ application จะมี  down time

หวังว่าจะเป็นประโยชน์ครับ 🙂

Be First to Comment

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: