มาใช้ Google Cloud Storage กับ Kubernetes กันเถอะ

Patipat Ponyanan
Grean Developers Family
2 min readJan 23, 2018

ที่มาของปัญหา

โดยปกติแล้วเวลาที่เรานำ app ของเราไป deploy ใน kubernetes สิ่งที่เกิดขึ้นคือ data ที่อยู่ใน pod นั้นจะไม่คงอยู่ไปด้วย เมื่อ pod หายไป data ก็หายไปเช่นกัน

ตัวอย่างเช่น. app ของเรามีการทำงานคือรับรูปภาพจาก user และทำการ crop เป็นวงกลมเพื่อใช้เป็นโปรไฟล์ของ user แต่ด้วยเหตุการณ์อะไรไม่รู้ หาก pod ที่เราใช้งานอยู่หายไป สิ่งที่เกิดขึ้นก็คือ รูปภาพทั้งหมดก็จะหายไปด้วย

ถึงแม้ใน kubernetes เมื่อ pod หายไป ตัว kubernetes เองก็จะสร้าง pod ขึ้นมาทดแทน แต่สิ่งที่เกิดขึ้นคือไม่มีรูปภาพทั้งก่อนและหลัง crop แล้ว

ถ้าหากเราต้องการเก็บรูปภาพไว้เพื่อให้ pod ต่อไปสามารถขึ้นมาทำงานต่อได้ หรือเพื่อให้อีกแอพนึงดึงรูปภาพไปใช้ เราจะทำอย่างไร

ปัญหานี้จะแก้ได้โดยการใช้ volume มาเก็บรูปภาพ ซึ่งเปรียบเสมือน storage ที่มี lifecycle ไม่เกี่ยวข้องกับ pod เมื่อ pod ตายไป data ที่เก็บไว้ใน volume ก็ยังอยู่ทำให้เมื่อ pod ใหม่เกิดขึ้นมาสามารถทำงานต่อได้ หรือเมื่อ app อื่นต้องการดึงรูปภาพไปใช้ก็สามารถ provide ให้ได้เช่นกัน

ซึ่ง volume เองก็มีมากมายหลายประเภทเหลือเกิน วันนี้เราจะมาใช้ Google Cloud Storage ซึ่งเป็น service ให้บริการ object storage มาเป็น storage ในการเก็บ data บน kubernetes กัน เหตุผลที่ใช้ Google Cloud Storage เพราะว่าราคาไม่แพงและมีความ availability ที่สูงทำให้ไม่ต้องกังวลเรื่อง request ที่วิ่งเข้าไปหา object ต่างๆ

และเพื่อไม่ให้กระทบการเขียนโค๊ดและตัว app มีความยืดหยุ่นไม่ยึดติดกับ platform เราจึงใช้ volume ประเภท hostPath ซึ่งเป็นการให้ pod ใช้ storage บน node ที่ pod รันอยู่ สิ่งที่เกิดขึ้นคือตัว app เองไม่ต้องรู้จัก GCS เลย รู้เพียงแค่ว่าจะเขียนอ่านไฟล์จากที่ใดใน filesystem (พาทไหน ไดเรอทอรี่ไหน) ทำให้ไม่ต้องใช้ sdk,api เพื่อติดต่อกับ GCS และเมื่อวันใดต้องการเปลี่ยนค่าย cloud หรือย้าย Server ก็สามารถทำได้โดยที่ไม่ต้องยุ่งกับตัว code อีกด้วย

วิธีการแก้ไขปัญหา

วิธีการที่เราจะแก้ปัญหาก็คือ ใช้ GCS(Google Cloud Storage) เก็บข้อมูลทั้งหมด และทำการ Mount เข้ากับเครื่อง Node และเวลาที่ pod ต้องการจะใช้งานก็ Mount volume มาที่ host อีกที

ขั้นตอนการดำเนินงาน

สิ่งที่เรากำลังจะทำมีสองเรื่องใหญ่ๆ ก็คือ
Part 1: ทำการ mount GCS Bucket เข้ากับเครื่อง Node เพื่อให้ Node สามารถใช้งาน bucket ได้เหมือนเป็น filesystem ของตัวเครื่อง Node เอง
tool ที่ใช้คือ gcsfuse

Part 2: ทำการ mount directory ของเครื่อง Node(จาก Part1) เข้ากับ Pod

Part1

1. สร้าง Bucket ที่ GCS และทำการ enable json api ของ GCS
2. สร้าง Service Account เพื่อให้ Node ของเรา มีสิทธิในการใช้งาน Bucket ของเรา
3. ไปที่เครื่อง Node ของเราเพื่อ install gcsfuse กันครับ
4. ทำการ Mount bucket กับ Node ครับ

gcsfuse  -o allow_other -o nonempty--dir-mode 777 --key-file <pathของ(2)> <BucketName> <directory>

5. ทดสอบสร้าง เขียน อ่าน ลบ ไฟล์ดูครับ ผลลัพธ์จะต้องเหมือนกันในทั้งในเครื่อง Node และ Bucket

Part2

จากพาทแรกเราเตรียมระดับ Node เรียบร้อยแล้ว ต่อมาจะลุยระดับ Pod กันครับ

สิ่งที่ต้องทำคือบอก kubernets ว่า “เราอยากให้ pod ของเรามี volume ที่ mount กับเครื่อง node ”
และ volume ที่ kubernetes มีตอบโจทย์เราก็คือ hostPath ซึ่งมีการคอนฟิคดังนี้

volumeMounts: บอก pod ว่าจะ mount ที่ไหน
volumes : บอก node ว่าจะ mount ที่ไหน
name เป็น key-value ที่ทำให้ volumeMounts แมพเข้ากับ volumes

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: hello-gcs
spec:
template:
metadata:
name: sampleapp
spec:
containers:
- name: hello-gcs
image: helloMedium
volumeMounts:
- mountPath: /some/dir/in/pod
name: hello-medium

nodeSelector:
poc: fuse
volumes:
- name: hello-medium
hostPath:
path: /some/dir/in/node

และในกรณีที่มี node เยอะมากก็สามารถกำหนด ให้ pod ไปเกิดที่เฉพาะ node ที่เราต้องการได้ โดยการแปะ label ที่ node แล้วกำหนด nodeSelector ให้ตรงกันครับ

สรุปผลการดำเนินงาน

จากที่เราทำไปทั้งหมด เราก็จะได้ไม่ต้องกังวลว่าข้อมูลจะหายไปหรือไม่ เมื่อ pod ร่วงไป เพราะเราเก็บข้อมูลเหล่านั้นไว้ที่ Google Cloud Storage แล้ว ทำให้ pod ใหม่ที่เกิดขึ้นมาสามารถทำงานแทนต่อได้ รวมถึงยังลดงานให้ Developer เพราะไม่ต้องยุ่งกับ sdk,api รวมถึงเมื่อย้าย platform ก็ไม่ต้องยุ่งกับตัว code อีกด้วย

และขอบคุณทุกคนที่เข้ามาอ่าน หวังว่าบทความนี้จะเป็นประโยชน์ต่อทุกคนนะครับ หากมีข้อสงสัยหรือข้อเสนอแนะก็สามารถคอมเม้นกันมาได้เลยะนะครับ ขอบคุณครับ

--

--