บทเรียนจาก 20 ปีของวิศวกรรมความน่าเชื่อถือของไซต์
(sre.google)- Google SRE สรุปประสบการณ์ในการยกระดับความน่าเชื่อถือ จากจุดเริ่มต้นที่ดำเนินงานด้วยศูนย์ข้อมูลขนาดเล็กและสคริปต์ Python ไปสู่สภาพแวดล้อมที่มีขนาดคอมพิวต์ใหญ่ขึ้น มากกว่า 1,000 เท่า และเครือข่ายใหญ่ขึ้น มากกว่า 10,000 เท่า
- ในการตอบสนองต่อเหตุขัดข้อง ความปลอดภัยของมาตรการบรรเทาผลกระทบ ต้องมาก่อนการลงมือแก้ไขอย่างรวดเร็ว และขั้นตอนกู้คืนที่ผิดพลาดอาจทำให้ความล้มเหลวลุกลามเป็นลูกโซ่มากกว่าลดเหตุขัดข้อง
- กรณีของ YouTube และ Google Calendar แสดงให้เห็นความจำเป็นของ การปล่อยแบบคานารี ที่จำกัดการเปลี่ยนแปลงระดับทั่วโลก, Big Red Button ที่ย้อนกลับได้ทันที และการทดสอบแบบบูรณาการที่ตรวจสอบเส้นทางการใช้งานจริง
- เมื่อ dependency หลักล่ม เช่น เหตุขัดข้องของโทเค็น OAuth ในปี 2017 ไม่เพียงผู้ใช้เท่านั้นที่ได้รับผลกระทบ แต่ระบบตอบสนองภายในก็สั่นคลอนด้วย จึงจำเป็นต้องมี ช่องทางสื่อสารสำรอง และการลดประสิทธิภาพอย่างนุ่มนวล
- การ rollout บ่อยครั้ง, การบรรเทาผลกระทบแบบอัตโนมัติ, การซ้อมกู้คืนจากภัยพิบัติ และความหลากหลายของฮาร์ดแวร์ คือหลักปฏิบัติที่ช่วยลด MTTR และหลีกเลี่ยงจุดล้มเหลวเดี่ยวในระบบกระจายที่ซับซ้อน
การเปลี่ยนแปลงด้านสเกลที่ Google SRE เผชิญตลอด 20 ปี
- เมื่อ 20 ปีก่อน Google ดำเนินงานศูนย์ข้อมูลขนาดเล็กสองแห่ง แต่ละแห่งมีเซิร์ฟเวอร์หลายพันเครื่อง และมี ลิงก์เครือข่าย 2.4G สองเส้นเชื่อมต่อกันเป็นวงแหวน
- การดำเนินงานในเวลานั้นพึ่งพา สคริปต์ Python เช่น
Assigner,Autoreplacer,Babysitterและไฟล์คอนฟิกที่มีชื่อเซิร์ฟเวอร์แต่ละเครื่องอยู่มาก - ฐานข้อมูลเครื่องขนาดเล็กที่ชื่อ MDB ถูกใช้เพื่อจัดระเบียบและดูแลข้อมูลเซิร์ฟเวอร์แต่ละเครื่องอย่างต่อเนื่อง
- ปัจจุบันพลังคอมพิวต์ขยายใหญ่ขึ้น มากกว่า 1,000 เท่า และเครือข่ายใหญ่ขึ้น มากกว่า 10,000 เท่า แต่ความพยายามด้านปฏิบัติการต่อเซิร์ฟเวอร์กลับลดลง และความน่าเชื่อถือของ service stack ดีขึ้น
- เครื่องมือปฏิบัติการพัฒนาจากชุดสคริปต์ ไปเป็นระบบนิเวศของบริการ และต่อมาเป็น แพลตฟอร์มแบบบูรณาการ ที่ให้ความน่าเชื่อถือพื้นฐาน
หลักการตอบสนองที่ได้จากเหตุขัดข้องของ YouTube
- ในปี 2016 YouTube ประสบ เหตุขัดข้องทั่วโลกนาน 15 นาที จากบั๊กในระบบ distributed memory caching ทำให้ความสามารถในการให้บริการวิดีโอหยุดชะงัก
- มาตรการบรรเทาผลกระทบต้องเหมาะสมกับความรุนแรงของเหตุขัดข้อง
- ระหว่างเหตุขัดข้องของ YouTube ขั้นตอน load-shedding ที่มีความเสี่ยงไม่สามารถแก้เหตุขัดข้องได้ และก่อให้เกิดความล้มเหลวแบบลูกโซ่
- มาตรการบรรเทาที่มีความเสี่ยง ในกรณีดีที่สุดอาจแก้เหตุขัดข้องได้ แต่ในกรณีแย่ที่สุด หากทำงานผิดพลาดก็อาจยืดเวลาขัดข้องให้นานขึ้น
- แม้สถานการณ์จะรุนแรงถึงขั้นต้องข้ามขั้นตอนมาตรฐาน ก็ควรสังเกตและประเมินความรุนแรงก่อนแล้วค่อยเลือกดำเนินการ
- กลไกกู้คืนต้องได้รับการทดสอบอย่างเพียงพอก่อนเกิดเหตุฉุกเฉินจริง
- การรันขั้นตอนบรรเทาผลกระทบที่มีความเสี่ยงเป็นครั้งแรกระหว่างเหตุขัดข้อง เหมือนกับการลองใช้บันไดเป็นครั้งแรกขณะอพยพจากไฟไหม้ตึกสูง
- ต้องตรวจสอบล่วงหน้าว่าขั้นตอนกู้คืนทำงานที่จำเป็นได้จริงหรือไม่ และผู้รับผิดชอบรู้วิธีดำเนินการหรือไม่
- การทดสอบเองยังช่วยลดความเสี่ยงเมื่อดำเนินมาตรการนั้นด้วย
- การเปลี่ยนแปลงทั้งหมดควรจำกัดขอบเขตผลกระทบด้วย การปล่อยแบบคานารี
- การเปลี่ยนคอนฟิก caching ส่งผลโดยไม่ตั้งใจ ทำให้บริการ YouTube หยุดชะงักอย่างหนักเป็นเวลา 13 นาที
- หากทยอยปล่อยการเปลี่ยนแปลงระดับทั่วโลกด้วย กลยุทธ์คานารี ก็อาจจำกัดเหตุขัดข้องได้ก่อนเกิดผลกระทบทั่วโลก
- เอกสารที่เกี่ยวข้องมี บทความวิจัยเรื่องกลยุทธ์คานารี และ วิดีโอการบรรยาย SREcon
Rollback และการทดสอบที่ได้เรียนรู้จากเหตุขัดข้องของ Calendar
- การเปลี่ยนแปลงที่มีความเสี่ยงต้องมี Big Red Button ที่กำหนดไว้ล่วงหน้า
- Big Red Button คือกลไกความปลอดภัยที่เรียบง่ายและทำได้ง่าย เพื่อย้อนกลับสาเหตุที่ทำให้เกิดสถานะไม่พึงประสงค์
- เคยมีกรณีที่วิศวกรคนหนึ่งถอดปลั๊กคอมพิวเตอร์เดสก์ท็อปก่อนที่การเปลี่ยนแปลงจะแพร่กระจาย จึงเฉียดฉิวหลีกเลี่ยงเหตุขัดข้องครั้งใหญ่ได้
- เมื่อวางแผน rollout สำคัญ ควรพิจารณาว่า “Big Red Button ของฉันคืออะไร?” และทุก dependency ของบริการควรมีกลไกที่ใช้ได้ในภาวะฉุกเฉิน
- บทความที่เกี่ยวข้องคือ Generic Mitigations
- Unit test อย่างเดียวไม่เพียงพอ ต้องมี integration test
- Unit test ตรวจสอบว่าคอมโพเนนต์แต่ละตัวทำงานตามที่คาดไว้หรือไม่ แต่ไม่สามารถจำลองสภาพแวดล้อม runtime และข้อกำหนดของ production ได้ครบถ้วน
- Integration test ใช้ตรวจสอบว่างานและ task สามารถ cold start ได้หรือไม่ และคอมโพเนนต์ต่าง ๆ ร่วมกันสร้างระบบตามที่ต้องการได้หรือไม่
- ในเหตุขัดข้องของ Calendar เส้นทางทดสอบต่างจากเส้นทางที่ใช้งานจริง แม้จะมีการทดสอบจำนวนมาก แต่ก็ไม่ได้ช่วยประเมินว่าการเปลี่ยนแปลงจะทำงานอย่างไรในโลกจริง
เหตุขัดข้องของโทเค็น OAuth ปี 2017 และความต่อเนื่องของการดำเนินงาน
- ในเดือนกุมภาพันธ์ 2017 โทเค็น OAuth ที่ใช้งานไม่ได้ทำให้ผู้ใช้หลายล้านคนถูกล็อกเอาต์จากอุปกรณ์และบริการ และอุปกรณ์ OnHub กับ Google WiFi 32,000 เครื่อง ทำการรีเซ็ตเป็นค่าโรงงาน
- ความล้มเหลวในการเข้าสู่ระบบทำให้คำขอกู้คืนบัญชีแบบแมนนวลเพิ่มขึ้น 10 เท่า และ Google ใช้เวลาประมาณ 12 ชั่วโมง จึงกู้คืนจากเหตุขัดข้องได้อย่างสมบูรณ์
- การตอบสนองต่อเหตุขัดข้องต้องมีช่องทางสำรองที่แยกจากช่องทางสื่อสารหลัก
- ในเวลานั้นทีมต่าง ๆ คาดว่าจะสามารถจัดการเหตุขัดข้องผ่าน Google Hangouts และ Google Meet ได้
- แต่ในสถานการณ์ที่ ผู้ใช้ 350 ล้านคน ถูกล็อกเอาต์จากอุปกรณ์และบริการ การพึ่งพาบริการของ Google จึงไม่เหมาะสม
- ต้องเตรียมและทดสอบช่องทางสื่อสารสำรองที่แยก dependency ออกจากกัน
- บริการต้องทำงานต่อได้ด้วยรูปแบบ การลดประสิทธิภาพอย่างนุ่มนวล (graceful degradation) แม้ในสถานการณ์ยกเว้น
- การแบ่ง availability เป็นเพียง “ปกติเต็มที่” หรือ “หยุดชะงักทั้งหมด” ยังไม่เพียงพอ
- หากยังคงฟังก์ชันขั้นต่ำไว้ได้ในโหมดประสิทธิภาพลดลง ก็จะมอบประสบการณ์ผู้ใช้ที่สม่ำเสมอยิ่งขึ้น
- การลดประสิทธิภาพอาจไม่ปรากฏให้ผู้ใช้เห็น และบริการควรถูกออกแบบให้ทำงานต่อได้แม้ในสถานการณ์ผิดปกติ
ภัยพิบัติ, อัตโนมัติ, rollout และความหลากหลายของฮาร์ดแวร์
- ความทนทานต่อภัยพิบัติและการทดสอบการกู้คืนเป็นองค์ประกอบสำคัญของกลยุทธ์ความต่อเนื่องทางธุรกิจ
- การทดสอบ resilience ตรวจสอบว่าบริการหรือระบบสามารถทนต่อเหตุขัดข้อง ความหน่วง และการหยุดชะงักได้หรือไม่
- การทดสอบ recovery ตรวจสอบว่าบริการสามารถกลับสู่สถานะปกติได้หรือไม่หลังจากปิดระบบทั้งหมด
- ต้องสมมติสถานการณ์สุดขั้ว เช่น ภัยธรรมชาติหรือการโจมตีทางไซเบอร์ เหมือนใน Weathering the Unexpected
- กิจกรรมที่ทีมทบทวนสถานการณ์แบบ tabletop game เช่น “จะเกิดอะไรขึ้นหากการเชื่อมต่อเครือข่ายบางส่วนขาดโดยไม่คาดคิด?” ก็มีประโยชน์
- สำหรับเหตุขัดข้องที่มีสัญญาณชัดเจน การบรรเทาผลกระทบแบบอัตโนมัติ เป็นวิธีลด MTTR
- ในเดือนมีนาคม 2023 อุปกรณ์เครือข่ายหลายชุดในศูนย์ข้อมูลหลายแห่งล้มเหลวแทบพร้อมกัน ทำให้เกิด packet loss ในวงกว้าง
- ระหว่าง เหตุขัดข้อง 6 วันนี้ บริการประมาณ 70% ได้รับผลกระทบในระดับต่าง ๆ ขึ้นอยู่กับตำแหน่งที่ตั้ง โหลดของบริการ และคอนฟิกในขณะเกิดเหตุเครือข่ายขัดข้อง
- สัดส่วนบริการที่ได้รับผลกระทบ: {p:70}
- หากมีสัญญาณชัดเจนว่าเกิดความล้มเหลวเฉพาะอย่าง ก็สามารถเริ่มมาตรการบรรเทาแบบแมนนวลโดยอัตโนมัติเพื่อลด MTTR ได้
- บางครั้งการหลีกเลี่ยงผลกระทบต่อผู้ใช้ก่อน แล้วค่อยวิเคราะห์สาเหตุราก อาจเป็นทางเลือกที่ดีกว่า
- ยิ่งช่วงห่างระหว่าง rollout นานเท่าใด ก็ยิ่งตัดสินความปลอดภัยของการเปลี่ยนแปลงได้ยากขึ้น
- ในเดือนมีนาคม 2022 เหตุขัดข้องของระบบชำระเงินทำให้ลูกค้าทำธุรกรรมไม่สำเร็จ และ Pokémon GO Community Day ถูกเลื่อนออกไป
- สาเหตุคือการลบฟิลด์เดียวในฐานข้อมูล และดูเหมือนเป็นการเปลี่ยนแปลงที่น่าจะปลอดภัย เพราะการใช้งานฟิลด์นั้นถูกลบออกจากโค้ดแล้ว
- แต่เนื่องจากรอบ rollout ที่ช้าของบางส่วนในระบบ ระบบ live จึงยังคงใช้ฟิลด์นั้นอยู่
- ในระบบหลายคอมโพเนนต์ที่ซับซ้อน ความล่าช้าในการ rollout ที่ยาวนานทำให้การตัดสินความปลอดภัยของการเปลี่ยนแปลงหนึ่ง ๆ ยากมาก
- การทำ rollout บ่อยครั้ง ควบคู่กับการทดสอบที่เหมาะสม สามารถลดความล้มเหลวไม่คาดคิดประเภทนี้ได้
- ฮาร์ดแวร์เวอร์ชันเดียวในระดับ global อาจกลายเป็น จุดล้มเหลวเดี่ยว ได้
- หากฝากฟังก์ชันสำคัญไว้กับอุปกรณ์รุ่นเดียว การดำเนินงานและการบำรุงรักษาอาจเรียบง่ายขึ้น
- แต่หากรุ่นนั้นเกิดปัญหา ฟังก์ชันสำคัญนั้นก็จะไม่สามารถทำงานต่อได้
- ในเดือนมีนาคม 2020 อุปกรณ์เครือข่ายที่มีบั๊ก zero-day ซึ่งยังไม่ถูกค้นพบเผยบั๊กออกมาเมื่อรูปแบบทราฟฟิกเปลี่ยนไป และเมื่อมีการใช้รุ่นและเวอร์ชันเดียวกันทั่วทั้งเครือข่าย จึงเกิดเหตุขัดข้องระดับภูมิภาคอย่างมีนัยสำคัญ
- เนื่องจากมี network backbone หลายชุด จึงสามารถส่งทราฟฟิกที่มี priority สูงไปยังเส้นทางทางเลือกที่ยังทำงานอยู่ได้ และหลีกเลี่ยงเหตุขัดข้องทั้งหมด
- บั๊กแฝงในโครงสร้างพื้นฐานสำคัญอาจซ่อนอยู่จนกว่าจะเกิดเหตุการณ์ที่ดูเหมือนไม่มีพิษภัย และการรักษาความหลากหลายของโครงสร้างพื้นฐานอาจเป็นความแตกต่างระหว่างเหตุขัดข้องที่มีปัญหากับเหตุขัดข้องทั้งหมด
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
บทความยอดเยี่ยม และดูเหมือนว่า นำไปประยุกต์ใช้ได้อย่างกว้างขวาง ไม่ได้มีส่วนไหนที่เป็นแนว “เรื่องนี้ใช้ได้เฉพาะที่ Google เท่านั้น” เป็นพิเศษ
ช่องทางสื่อสาร, ช่องทางสำรอง, และแม้แต่ช่องทางสำรองของช่องทางสำรอง นั้นสำคัญมากจริง ๆ ที่ Netflix ตอนเลือกผู้ให้บริการสำหรับระบบที่ใช้ระหว่างเกิดเหตุขัดข้อง เราจะตรวจเสมอว่าไม่ได้รันอยู่บน AWS ส่วนที่ reddit เรามี IRC สำรองไว้บนเซิร์ฟเวอร์ในออฟฟิศ เผื่อ IRC หลักใช้ไม่ได้
ผมเคยได้ยินว่า Google ก็มีเซิร์ฟเวอร์ IRC สำรองอยู่บน AWS แต่เรื่องนั้นอาจเป็นแค่ตำนานก็ได้ ประเด็นสำคัญคือการมี ช่องทางติดต่อสำรอง ที่แยกจากโครงสร้างพื้นฐานของตัวเองให้มากที่สุด
ทีมนั้นอยู่บนเส้นทางสำคัญ ดังนั้นถ้ามีการเรียกเข้ามาเพราะระบบของเรา ความเป็นไปได้ที่ไม่ใช่แค่ Google Meet แต่ Google.com จะล่มไปด้วยก็ไม่ได้ต่ำเลย อีเมลก็ใช้ไม่ได้เพราะ Gmail มือถือที่ใช้ทำงานก็ใช้ไม่ได้เพราะ Google Fi และ ISP ที่บ้านก็เป็น Google Fiber/Webpass เลยจำเป็นต้องมีชั้นสำรองเพิ่มเติม
ดังนั้นที่ Google จึงมี เซิร์ฟเวอร์ IRC สำรอง สำหรับการสื่อสารอยู่จริง ผมจะไม่บอกว่ามันอยู่ที่ไหน แต่ด้วยเหตุผลนี้เองจึงตั้งไว้นอกโครงสร้างพื้นฐานของ Google อย่างชัดเจน
ในแง่ที่ว่า “นำไปใช้ได้กว้างและไม่ใช่เรื่องที่ใช้ได้แค่ที่ Google” สิ่งที่ผมแทบไม่เคยเห็นที่อื่นคือ ห้อง panic room สำหรับปฏิบัติการ หมายถึงห้องปลอดภัยที่มี VPN สำรองเข้าสู่สภาพแวดล้อมปฏิบัติการ
วันหนึ่ง SAN ฝั่งปฏิบัติการเริ่มผิดปกติจนดาต้าเซ็นเตอร์ on-premises ล่ม และ Atlassian ก็ล่มไปด้วย ไม่มี Jira ไม่มี Confluence, CI/CD ก็น่าจะไม่มี และไม่มีเอกสารขั้นตอนกู้คืนที่เป็นระเบียบ เหลือแค่ความรู้แบบชนเผ่า
ผู้คนโกรธจัด และก็สมควรแล้ว การเอาระบบที่ลูกค้าใช้งานกับระบบที่เกี่ยวกับโครงสร้างพื้นฐานไปใส่ไว้ในตะกร้าเดียวกันเป็นเรื่องเสี่ยงมากจริง ๆ
อย่างน้อยก็เป็นแบบนั้นเมื่อ 2 ปีก่อน ตอนที่ผมยังทำงานอยู่ที่นั่น
สักวันหนึ่งอยากได้ยินวิธีแก้ปัญหา การเริ่มระบบจากศูนย์แบบ cold start เต็มรูปแบบ บริษัทที่มีสแตกขนาดใหญ่ของตัวเองมักมีการพึ่งพาแบบวนกลับในโครงสร้างพื้นฐานหลัก
Software-defined networking ต้องมีซอฟต์แวร์บางอย่างรันอยู่ก่อนจึงจะเริ่มการเราต์แพ็กเก็ตใหม่ได้ เครื่องที่ไม่มีดิสก์ต้องมีสตอเรจสำหรับบูต และบริการยืนยันตัวตนต้องเข้าถึงสตอเรจก่อนเพื่อบูตสแตรปการให้สิทธิ์ด้านความปลอดภัย
ตอนนี้จัดการด้วยการรันหลายรีเจียนที่เป็นอิสระต่อกัน แล้วบูตสแตรปดาต้าเซ็นเตอร์ที่ดับสนิทจากโครงสร้างพื้นฐานที่มีอยู่ แต่ผมไม่เคยได้ยินว่ามีใครยกทั้งสแตกกลับขึ้นมาจากสภาพตัดไฟทั้งหมดจริง ๆ
เมื่อไม่กี่ปีก่อนตอนที่ Facebook ทำเครือข่ายปฏิบัติการพังทั้งชุด เครื่องต่าง ๆ ยังเปิดอยู่ และการเชื่อมต่อภายในบางส่วนก็ยังเหลืออยู่ ถ้าเกิดเหตุอย่างพายุสุริยะขนาดใหญ่จนโครงข่ายไฟฟ้าทั่วโลกดับเป็นเวลานาน กระทั่งเครื่องปั่นไฟก็ใช้จนหมด ก็ไม่มีหลักประกันว่าคลาวด์อย่าง AWS หรือ GCP จะฟื้นกลับมาได้แน่นอน
คงน่าจะมีดาต้าเซ็นเตอร์เฉพาะทางขนาดเล็กบางแห่งที่มีไฟสำรองชั้นยอด และสามารถแยกตัวจากไฟกระชากในโครงข่ายไฟฟ้าได้อย่างสมบูรณ์
ที่ชั้นบนของสแตก มันมีประโยชน์ในการติดตาม dependency ที่ผู้เขียนไลบรารีเพิ่มเข้ามาเงียบ ๆ ส่วนที่ชั้นล่าง มันช่วยรับประกันว่าสิ่งที่ควรอยู่ชั้นล่างสุดนั้นอยู่ชั้นล่างสุดจริง ๆ
เรายังมีการสตาร์ตและหยุดคลัสเตอร์เสมือนแบบอัตโนมัติเพื่อไม่ให้ขั้นตอนที่บันทึกไว้ล้าสมัย และตลอด 6 ปีที่ผมเป็น SRE ผมเห็นขั้นตอนนั้นลดจาก 90 วันเหลือน้อยกว่า 1 ชั่วโมง
สิ่งอย่างการจัดการกุญแจเข้ารหัสระดับโกลบอลที่ต้องใช้ออบเจ็กต์ทางกายภาพ ก็มีการซ้อมเริ่มใหม่ตั้งแต่ต้นเป็นประจำ และการซ้อม DiRT ประจำปีก็พยายามตรวจสอบว่าไม่มีบุคคล ทีม หรือออฟฟิศใดเป็นเงื่อนไขจำเป็นต่อการทำให้ระบบทำงานต่อเนื่อง
ถ้าเริ่มช้าจะเจ็บปวดมาก แต่ถ้าทำตั้งแต่ต้นก็จะคุ้นเคยได้เร็ว และจับการเปลี่ยนแปลงที่ทำให้พังหรือ dependency แปลก ๆ ได้ตั้งแต่เนิ่น ๆ
ใช้กับฮาร์ดแวร์ได้ด้วย สถาปัตยกรรมจะเปลี่ยนไปเพื่อรองรับสถานการณ์ที่บางอย่างถูกถอดปลั๊กหรือรีเซ็ต ต้องมีอัตโนมัติมากขึ้น การจัดการเวอร์ชัน และการจัดการการเปลี่ยนแปลงมากขึ้น และผลก็คือนอกจากช่วยป้องกันเหตุขัดข้องกับกู้คืนได้เร็วแล้ว งานโดยรวมยังเร็วขึ้นและง่ายขึ้นด้วย เป็นการเปลี่ยนแปลงวัฒนธรรมครั้งใหญ่
เท่าที่จำได้ บางส่วนของแนวทางนี้ถือเป็นข้อมูลอ่อนไหว เลยจะไม่ลงรายละเอียดมากกว่านี้
น่าสนใจด้วยว่าโครงข่ายไฟฟ้าไหนเคย cold start บ่อยที่สุด ตามอุดมคติ ที่แบบนั้นควรทำได้ดีอยู่แล้ว น่าจะเป็นที่ไหนสักแห่งในแคริบเบียนหรือแอฟริกา
แต่ cold start ของโครงข่ายไฟฟ้าขนาดเล็ก เช่น เกาะห่างไกลที่มีเครื่องปั่นไฟดีเซลหนึ่งเครื่องกับโซลาร์ อาจง่ายเกินไปจนไม่ใช่กรณีศึกษาที่ดี
เห็นได้ชัดว่าอินเทอร์เน็ตเองไม่สามารถ cold start ได้เหมือนโครงข่ายไฟฟ้ากระแสสลับ เพราะมี AS มากเกินไป แค่ลองคิดสักครู่ว่า AS ย่อมาจากอะไร ก็จะเข้าใจว่าทำไม cold start ที่ประสานงานและซ้อมล่วงหน้าจึงเป็นไปไม่ได้
หากต้องการลงลึกในหัวข้อนี้ ผมกำลังอ่าน Building Secure and Reliable Systems ของ Google ใกล้จบแล้ว ซึ่งไม่ใช่อ่านเล่นเบา ๆ แต่ใกล้เคียงกับ ตำราเรียน จริงจัง
เป็นหนังสือที่ค่อนข้างน่าสนใจ และหลายอย่างดูเหมือนสามัญสำนึก แต่ก็มีคำกล่าวว่า “สามัญสำนึก” ในตัวมันเองเป็นคำที่ขัดแย้งกันอยู่ หนังสือนี้จึงมีประโยชน์ในการรีเฟรชความรู้ทั้งหมดในคราวเดียว
ช่วงหลังได้ยินมาว่าบางบริษัทปิดองค์กร SRE แล้วโยกคนไปอยู่ทีม SWE มีข่าวลือว่า LinkedIn, Adobe, Robinhood ทำแบบนั้น
เลยทำให้คิดว่า SRE เป็นผลพลอยได้ของเศรษฐกิจฟองสบู่ที่เงินหาง่ายหรือเปล่า เราจะดำเนินงานโดยไม่ต้องจ่ายต้นทุนสูงเพื่อแยกทีม SRE ออกมาต่างหากไม่ได้หรือ
เหมือนที่ผู้ดูแลระบบหรือ QA tester ส่วนใหญ่หายไป และหลายฟังก์ชันย้ายไปอยู่กับทีมพัฒนาซอฟต์แวร์ ก็เลยสงสัยว่าอีก 10 ปี SRE จะยังเหลืออยู่ไหม
แต่ตอนนี้เป็นสถานการณ์ที่มีการเลิกจ้างต่อเนื่อง จึงมีบริษัทไม่มากที่ใส่ใจกับจุดนั้น แนวโน้มในอุตสาหกรรมที่ดึงนักพัฒนาไปแก้ปัญหาแม้จะไม่ใช่ขอบเขตความเชี่ยวชาญของตนจะไม่หายไป และจะยิ่งเด่นชัดในช่วงเศรษฐกิจถดถอย
full-stack developer เป็นตัวอย่างที่ดีของการรวมสองบทบาทเข้าด้วยกัน แต่ไม่ได้จ่ายค่าตอบแทนเป็นสองเท่า
อย่างไรก็ตาม ประเด็นที่เหลือยังถือว่าถูกต้องอยู่ ทุกวันนี้ DevOps ทำให้ทักษะที่นักพัฒนาต้องมีขยายกว้างขึ้น และทับซ้อนกับ SRE ค่อนข้างมาก บริษัทมีแนวโน้มจะลดทีม SRE แล้วกระจายความรับผิดชอบไปยังนักพัฒนา
อีกเหตุผลใหญ่คือ automation ถ้าอ่านไซต์ที่ลิงก์ไว้ไปนาน ๆ จะเห็นว่าในยุคแรกของ Google นั้น SRE ทำงานด้วยมือจำนวนมาก เช่น ดูกราฟเองระหว่าง deploy
ตอนนั้นแม้แต่ Google เองก็ยังมี automation ของระบบไม่เพียงพอ SRE จึงจำเป็นมาก ถ้าดูเรื่อง Sisyphus https://www.usenix.org/sites/default/files/conference/protec... ก็จะเข้าใจได้ในระดับหนึ่งว่า ความล้มเหลวของ Google ในการนำ automation แบบมาตรฐานมาใช้ตั้งแต่แรก ช่วยรับประกันความมั่นคงในงานของ SRE ได้อย่างไร
การส่งต่อการปฏิบัติการของซอฟต์แวร์ที่ตัวเองเขียนให้คนอื่นดูแลนั้นไม่สมเหตุสมผล ก็ให้ SWE เข้าเวร on-call ไปเลย ถ้าคิดว่างาน manual เป็นวิธีที่ดีที่สุด ก็ให้ทำเอง และถ้าอยู่ระดับนั้นก็ควรถูกเลิกจ้างในฐานะวิศวกรที่แย่
สัมภาษณ์กันเข้มข้นขนาดนั้น แต่กลับไม่รู้ว่าคอมพิวเตอร์ที่ตัวเองเขียนโปรแกรมอยู่ทำงานอย่างไร นั่นแปลก เรื่องอย่างการทำงานของระบบปฏิบัติการก็มีในหลักสูตรปริญญาตรีอยู่แล้ว การโยนเรื่องนี้ไปให้ตำแหน่งและบทบาทจำนวนมากที่มักมาจากผู้ดูแลระบบที่เรียนรู้เองเป็นหลักก็ดูแปลกเช่นกัน
SWE เก่ง ๆ ที่ผมรู้จักล้วนรู้ว่าระบบปฏิบัติการ คอมพิวเตอร์ และเครือข่ายทำงานอย่างไร
งานที่ SRE ทำอยู่ในตอนนี้ เช่น automation ทั่วไป การจัดหาเครื่องมือสำหรับนักพัฒนา และการปรับปรุง developer experience กำลังย้ายไปอยู่กับ ทีมแพลตฟอร์ม ผมคิดว่าบทบาทนี้จะเปลี่ยนไปมากในอนาคต
ทีม SRE หนึ่งทีมสามารถสนับสนุนทีมพัฒนาหลายทีมได้ และทีมพัฒนามักแทบไม่ได้ใช้เวลากับโครงสร้างพื้นฐานที่ซับซ้อนหรือแง่มุมของระบบกระจายศูนย์มากนัก เพราะไม่ใช่เรื่องที่ต้องกังวลเป็นประจำทุกวัน
ดังนั้นการมี องค์กรโครงสร้างพื้นฐาน ที่ขับเคลื่อนเป็นหน่วยงานต่างจากทีมพัฒนาเฉพาะทางจึงสมเหตุสมผล ไม่ว่าจะเรียกว่า SRE, ทีม SRE SWE หรือแค่ infra ก็ตาม เมื่อถึงสเกลหนึ่งขึ้นไป จะมีประเด็นที่ต้องดูแลข้ามทีมมากขึ้น และการแยกแบบนั้นจะถูกกว่า
การมี SRE เฉพาะทางทำให้มีผู้เชี่ยวชาญจริง ๆ ด้าน operations รวมถึงระบบ เครื่องมือ และ alert ที่เกี่ยวข้อง และยังทำให้ความรับผิดชอบต่อผลลัพธ์ชัดเจน แต่เพราะพวกเขาไม่ได้เป็นเจ้าของระบบที่ดูแลอยู่อย่างเต็มรูปแบบ จึงอาจเกิดปัญหาเชิงองค์กรได้
อาจเกิดกรณี “เราอยากปล่อย X แต่ SRE คัดค้าน” หรือในทางกลับกัน และคนที่ไม่ใช่ SRE ก็อาจไม่ต้องรับผิดชอบโค้ดที่ support ได้ยาก
ในทางกลับกัน ทีมวิศวกรรมที่ไม่มี SRE อาจลดปัญหาเชิงองค์กรและสังคมแบบนั้นได้ แต่ ความน่าเชื่อถือของการปฏิบัติการ จะกลายเป็นเพียงหนึ่งในหลายลำดับความสำคัญ
ในทางปฏิบัติ ผมคิดว่าหลายบริษัทกำลังตัดสินใจว่าจะไม่ให้ความสำคัญกับ reliability ในฐานะผลลัพธ์ทางธุรกิจมากนัก โดยเฉพาะเมื่อค่าเสียโอกาสของการพัฒนาฟีเจอร์สูงขึ้น
การบรรเทาอัตโนมัติ เป็นเรื่องที่ต้องคิดให้นานจริงๆ ตลอด 30 ปีในอาชีพ ผมเห็นหลายครั้งที่การบรรเทาอัตโนมัติทำให้ปัญหาแย่ลง ดังนั้นต้องพิจารณาอย่างรอบคอบว่าจำเป็นต้องมีการเยียวยาตัวเองจริงหรือไม่
ในปี 2014 ผมสร้างโซลูชันรายงานการแครชของมือถือสำหรับใช้ภายในบริษัท และบางส่วนของแบ็กเอนด์รันอยู่บนเซิร์ฟเวอร์เครื่องเดียวที่มี Redis เป็นจุดล้มเหลวเดี่ยว กระบวนการ failover เป็นแบบกึ่งอัตโนมัติ คือคนต้องตรวจสอบก่อนว่า alert นั้นถูกต้อง แล้วจึงเริ่มกระบวนการ
แม้มันจะล่มก็ไม่มีความเสียหายทางการเงินจริงๆ กรณีเลวร้ายที่สุดก็แค่นักพัฒนาแอปมือถือไม่สะดวกชั่วคราว ตลอด 10 ปีที่รันมา จำนวนครั้งที่ต้องทำ failover นับได้ด้วยนิ้วสองนิ้ว
ทั้งที่เป็นระบบที่ไม่มี SLA แต่ uptime กลับดีกว่าระบบภายในที่สำคัญกว่ามาก
ในทางกลับกัน ดูกรณีของ GitHub ได้: https://github.blog/2023-05-16-addressing-githubs-recent-ava..., https://github.blog/2018-10-30-oct21-post-incident-analysis/, https://www.datacenterknowledge.com/archives/2012/12/27/gith...
แน่นอนว่า GitHub ดำเนินงานในสเกลที่ใหญ่กว่ามาก ประเด็นคือ redundancy และการบรรเทาอัตโนมัติเพิ่มความซับซ้อน และโดยนิยามแล้วมันแทบไม่เคยถูกทดสอบ แต่กลับต้องทำงานในสถานการณ์ที่คาดไม่ถึง
ดังนั้นควรพิจารณา SLA และต้นทุนของเหตุขัดข้อง แล้วถ่วงดุลกับความซับซ้อนที่จะเพิ่มเข้ามาเพื่อป้องกันเหตุขัดข้อง บทเรียนแรกของผมคือราวปี 1998 ตอนที่นำ NetApp สองเครื่องมาผูกกันเป็นคอนฟิก high availability แล้วเครื่องหนึ่งล้มเหลวจนทำให้ดิสก์ทั้งหมดของอีกเครื่องเสียไปด้วย
ช่วงเวลาใกล้ๆ กันก็เกิดเรื่องแบบเดียวกันกับไฟร์วอลล์ Cisco PIX สองตัว และตั้งแต่นั้นมาผมก็ระมัดระวังกับ high availability รวมถึง failover/การบรรเทาอัตโนมัติมาโดยตลอด
อยากรู้ว่าในภาคปฏิบัติจัดการ ปุ่มแดงใหญ่ และการลดระดับประสิทธิภาพแบบตั้งใจทีละขั้นอย่างไร โดยเฉพาะอย่างยิ่ง ทำอย่างไรให้แน่ใจว่าสิ่งเหล่านี้ยังทำงานได้ในช่วงที่ระบบกำลังมีปัญหา
เช่น ใช้ feature flag ที่อิงกับฐานข้อมูลหรือไม่ และถ้าใช่ แล้วตอนที่ตัวฐานข้อมูลเองหรือ API สำหรับเข้าถึงโอเวอร์โหลดจะทำอย่างไร
หรือใช้แฟล็กเริ่มต้นแบบ static อย่าง environment variable หรือไม่ และในกรณีนั้นจะรับประกันได้อย่างไรว่าจะ deploy ได้เร็วพอ หรือมีวิธีอื่นไปเลยหรือไม่
แม้จะไม่ใช้ redundancy ในบางส่วนของ critical path แต่ถ้าระบบเรียบง่ายพอที่จะอยู่ในหัวของผู้ดูแลทุกคน และรีบูตหรือ rollback ได้ง่าย แบบนั้นอาจดีกว่า
แต่เมื่อบริษัทเริ่มให้คำมั่นอย่าง “uptime ระดับ five nines” ก็จะต้องมีความซับซ้อนระดับหนึ่ง เพื่อออกแบบระบบที่ยังคงรักษาคำมั่นนั้นไว้ได้พร้อมกับพัฒนาและปรับปรุงต่อไป
ที่ Google หากพิจารณาว่า cluster ใดไม่ healthy ก็จะทำ “backend drain” เป็นประจำ และมีระบบในชั้น API/load balancer ที่จัดการเรื่องนี้ได้อย่างรวดเร็ว
ที่อื่นๆ ผมเคยเห็นการจัดการด้วย flag ระดับแอปพลิเคชันด้วย เป็นแนว
kubectl editซึ่งชัดเจนว่าไม่ใช่อุดมคติ แต่ก็ใช้งานได้อย่างแรก ต้องรักษาให้เรียบง่าย แค่ตรวจ flag ง่ายๆ โดยไม่มี logic ซับซ้อนหรือ data store ที่ซับซ้อนจะดีกว่า
อย่างที่สอง วางไว้ให้ใกล้ source เท่าที่ทำได้ แต่อย่าเชื่อใจ client มากเกินไป เพราะอาจมีเวอร์ชันเก่า ความล่าช้าในการกระจาย หรือบั๊ก ดังนั้นควรให้ทั้งฝั่ง client และ server เลือกโหมด degradation ได้ และถ้าเลือกได้แค่ฝั่งเดียว ฝั่ง server จะดีกว่า
อย่างที่สาม ต้อง ทดสอบบ่อยๆ ด้วยทราฟฟิกจริง อย่าเชื่อ test environment ควรมีการทดสอบเป็นระยะในสเกลเล็กๆ เช่น 0.1% และทดสอบใหญ่ตามกำหนดการ ถ้าไม่เคยทดสอบ มันจะไม่ทำงานตอนจำเป็น และถ้ามันเคยทำงานเมื่อ 1 ปีก่อน ตอนนี้ก็มีโอกาสสูงที่จะไม่ทำงาน อุปกรณ์ที่ไม่ได้ทดสอบอาจเพิ่มความเสียหายมากกว่าช่วยแก้ปัญหา
สมมติว่าเพิ่มฟีเจอร์ใหม่ให้ Hacker News แสดงรูปโปรไฟล์ข้างคอมเมนต์ แน่นอนว่าเราทำทุกอย่างเป็น microservice อยู่แล้ว จึงสมมติว่า frontend page generator เรียกไปยัง profile service แล้ว profile service ไปค้นหาและส่งตำแหน่งรูปภาพกลับมา
ในฐานะส่วนหนึ่งของแผนเปิดตัว เราจัดทำเอกสาร ขั้นตอนปุ่มแดงใหญ่ ที่จะทำตามหากคอมโพเนนต์ใหม่ทำให้ profile service หรือ image storage โอเวอร์โหลด นั่นคือรันคำสั่งที่ชั้นเครือข่ายเพื่อจำกัดอัตรา request ขาออกจาก service ของผม และในเหตุฉุกเฉินก็คงตั้งเป็น 0
การค้นหาจะล้มเหลว แต่ page generator ถูกออกแบบให้ degrade แบบค่อยเป็นค่อยไป โดยยังคง render ข้อความคอมเมนต์ต่อไปโดยไม่มีรูปโปรไฟล์
นี่ไม่ใช่เอกสารออกแบบจริง และไม่ใช่คำแนะนำว่าควรสร้างอะไรอย่างไร เป็นเพียงภาพวาดด้วยสีเทียนเพื่ออธิบายประเด็นเท่านั้น
เคยทำด้วย CDB (constant database) ของ djb และเคยเห็นกรณีที่ poll ไฟล์ config JSON ผ่าน API หรือใช้ dbm/gdbm/Berkeleydb/leveldb
วิธีนี้ขยายไปใช้กับปุ่มแดงใหญ่อื่นๆ ได้ด้วย ไม่ได้สวยงามนัก แต่ผมเคยรันบริการที่ตรวจว่ามีไฟล์อยู่หรือไม่ เพื่อตัดสินใจว่าจะให้ health check ผ่านหรือไม่อยู่หลายครั้ง การนำ node ออกจากรอบของ load balancer ทำได้ง่ายพอๆ กับการสร้างไฟล์หนึ่งไฟล์
แก่นสำคัญคือ ถ้าฐานข้อมูลล่ม ระบบต้องใช้ ค่าคอนฟิกที่ทราบว่าดีล่าสุด เป็นค่าเริ่มต้น
ผมอยากเน้นประโยคที่ว่า “กลไกการกู้คืนต้องถูกทดสอบอย่างสมบูรณ์ก่อนเกิดเหตุฉุกเฉิน” จริงๆ ในฐานะคนที่กลายเป็น SRE ที่ Google โดยไม่คาดคิด และเป็นที่รู้จักทั่วทั้งบริษัทเพราะใช้ double negative ผิด นี่คือสิ่งที่สำคัญมากและต้องทำให้ถูกตั้งแต่แรก
ถ้าเป็น Googler ที่อยากรู้ ก็ลองค้น username ของผมภายในบริษัทดู จะพบว่าผมสร้างผลกระทบที่ใหญ่เกินกว่าจะวัดได้อย่างไร
วิธีที่ถูกที่สุดในการป้องกันเหตุขัดข้องคือจับให้ได้ตั้งแต่ช่วงต้นของวงจรชีวิต บั๊กซอฟต์แวร์คล้ายกับแมลงจริง ๆ ตอนแรกคือไข่ นั่นคือไอเดียการเปลี่ยนแปลง และตัวอ่อนที่ฟักออกมาคือ POC แรก พอไปถึงสภาพแวดล้อม production ก็กลายเป็นตัวเต็มวัยแล้ว
ถามว่าไม่มีระยะก่อนตัวเต็มวัยหรือ? มีสิ แอปพลิเคชันต้องผ่านหลายระยะก่อนจะโตเต็มที่ การหาบั๊กให้เจอก่อนที่มันจะโตเต็มวัยและวางไข่ได้ ถูกกว่ามาก
ถ้าการทำ canary deployment ยาก และ rollback ก็มีปัญหา ก็ควรเพิ่มการทดสอบให้มากขึ้นก่อน deploy ไป production ต้องหาบั๊กให้เจอเร็วด้วยวิธีให้มากที่สุดเท่าที่ทำได้ เช่น linter, unit test, end-to-end test, profiler, synthetic monitor, replica ของ production แบบ read-only, performance test เป็นต้น
feature flag, backward compatibility และอย่างอื่นก็มีประโยชน์ แต่ไม่มีอะไรชนะ Shift Left ได้
ถ้าสนใจรายการในทำนองเดียวกันจากมุมมองของคนที่ทำ SRE มา 15 ปีในสาย FinTech, ธนาคาร, hedge fund และคริปโตเคอร์เรนซี ขอแนะนำบทความนี้: https://x.com/alexpotato/status/1432302823383998471?s=20
ตัวอย่าง: “25. ถ้ามี rules engine ที่สร้างกฎใหม่ได้ง่ายกว่าการค้นหากฎเดิมด้วยเงื่อนไขตัวกรอง สุดท้ายก็จะมีกฎซ้ำซ้อนเต็มไปหมด”
“วิศวกรที่ส่งการเปลี่ยนแปลงซึ่งเกือบทำให้เกิดเหตุขัดข้อง ดึงปลั๊กไฟคอมพิวเตอร์เดสก์ท็อปของตัวเองก่อนที่การเปลี่ยนแปลงจะแพร่ออกไป จึงหลีกเลี่ยงเหตุขัดข้องใหญ่ได้อย่างหวุดหวิด” นี่หมายความว่ายังไงกันแน่?
ผลคือ SWE ฝั่ง infrastructure ไม่ได้สร้างปุ่มจริง ๆ แต่ใช้เวลาทั้งวันเขียน CLI งี่เง่า ๆ ตอนที่ผมออกมา เรื่องนี้ก็เริ่มเปลี่ยนไปมากแล้ว
ผมคิดว่า Google ควรเปิดเผยเหตุขัดข้องภายในให้มากกว่านี้ เหตุขัดข้องนี้โด่งดังมากเป็นพิเศษภายในบริษัท
แม้ในสเกลมหาศาล shell tool และ RPC client CLI ก็สามารถแตะเครื่องทุกเครื่องทั่วโลกได้ค่อนข้างเร็ว
psshนั่นคือเมื่อ 10 ปีก่อน จึงไม่รู้ว่ายังใช้แบบนั้นอยู่ไหม แต่วิธีนั้นเร็วอย่างน่าทึ่ง อาจเป็นงานประเภทนั้นก็ได้
แต่เมื่อ 20 ปีก่อนมันน่าจะพบได้บ่อยกว่า และแม้ตอนนี้ก็ยังอาจเกิดขึ้นได้ในองค์กรขนาดเล็ก