หลังจากผ่านตอนแรกไป เล่า spark on k8s แบบสั้นๆ
ก็ไปทำการบ้านทดลองนั่นๆ นี่ๆ มา ก็มาสรุปไว้หน่อย เผื่อมีคนเจอปัญหาเดียวกัน
โจทย์ที่ต้องทำคือ deploy pyspark app ไปรันบน k8s cluster ที่เตรียมไว้(มีคนเตรียมไว้ให้เแล้วจะขอไม่กล่าวถึง) โดยมีโจทย์เพิ่มสองข้อใหญ่ๆ คือ ตัว hadoop อยู่อีก cluster นึง และ cluster นี้ authenticate ด้วย kerberos
โดย app นี้ก็แค่สำหรับ PoC ก็เป็น job etl ง่ายๆ คือ อ่าน data จาก hive table จาก hadoop cluster แล้วก็เอามา transform แล้วก็เขียนลงไปในอีก table ใน hadoop cluster เดิม
สิ่งที่ต้องเตรียมจะมี 2 ส่วนหลักๆ คือ
- local สักที่ ที่จะรัน spark-submit ไปที่ k8s cluster
- spark image ที่ต้องเตรียม code ของเราไปรัน
มาดูข้อ 1 ก่อน คือที่ๆ เราจะรัน spark-submit
เราต้องเตรียมของประมาณนี้
- spark bin version 3
ซึ่งผมลองด้วย 3.1.3 นะ ไปลองด้วย 3.2 ละมีปัญหาเรื่อง ssl authentication(บน cluster ที่ผมลอง)
จริงๆ ลองมาทั้ง spark 2 และ 3 แหละ แต่ spark 2 ติดปัญหาที่มันไม่เอา config จำพวก hive-site.conf spark-env.sh อะไรพวกนี้ไปด้วย แต่ version 3 เตรียมให้ครบเลย เราสามารถใส่ conf เพิ่มได้แหละ แต่ต้องเพิ่มเยอะมากอะ กว่าจะครบ ==’
กลไกมันก็ลึกลับอยู่พอสมควรในการเตรียม config คือมันจะไปสร้าง(แบบอัตโนมัติ) configmap ไว้ตัวนึงแล้วให้ driver ไป mount เข้ามาผูกกับ spark_home (/opt/spark/conf) - ปิด configuration ของ spark บางตัว สำหรับการ PoC
ปิด ไป 3 ส่วนคับ คือ shuffle service, eventlog แล้วก็ dynamic allocation
ส่วนที่ 2 คือ spark image
เราต้องเตรียมของประมาณนี้
- ชุด configuration สำหรับ kerberos authentication ก็จะมี 3 ตัวหลักๆ คือ keytab file, /etc/krb5.conf และ /etc/hosts และฝัง command ในการรัน kinit เพื่อเตรียม ticket เป็นกลไกของ kerberos
- pyspark app ของเรา โดยเราต้อง modify Dockerfile ในการ build image
- driver image โดยเราสามารถทำตาม instruction ตาม manual (Running Spark on Kubernetes - Spark 3.5.0 Documentation) ได้เลย ตรงไปตรงมา แต่เราต้องแก้เพื่อเอา pyspark file ของเราแปะไปด้วย
note: ใน image นี้จะใช้สำหรับ driver และ executor เลย
ส่วนสุดท้ายคือคำสั่ง spark-submit
spark-submit \
–master k8s://your-cluster:port \
–deploy-mode cluster \
–conf spark.kubernetes.namespace=if-you-have \
–conf spark.kubernetes.container.image=your-image \
–conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \
–conf spark.kubernetes.container.image.pullPolicy=Always \
–conf spark.driver.extraJavaOptions=-Djavax.security.auth.useSubjectCredsOnly=false \
–conf spark.kubernetes.hadoop.configMapName=hadoop-properties \
local:///path/to/pyspark/app.py
โดยที่ทดลองจะรันเป็น cluster mode
มีติด configuration เพิ่มมา 2 ตัวคือ
spark.driver.extraJavaOptions=-Djavax.security.auth.useSubjectCredsOnly=false
เพื่อบังคับให้ kerberos ใช้ ticket ที่เราสร้างมาตอน kinitspark.kubernetes.hadoop.configMapName=hadoop-properties
เพื่อเซ็ต configuration ของ hadoop โดยเราต้องสร้าง configmap แล้วใส่ core-site.xml, hdfs-site.xml และ hadoop-env.sh ซึ่ง config นี้ทำงานกับ spark 3 เท่านั้น
ในบริบทของ cluster ที่ผมทดลองก็จะเซ็ตของประมาณนี้
พอ submit ไป สิ่งที่เกิดขึ้นจะประมาณนี้
- สร้าง configmap ที่เอา config file จาก $SPARK_HOME บนเครื่อง local ซึ่งในเครื่องผมก็จะมี hive-site.xml
- cluster สร้าง spark driver ด้วย spark-defaults.conf แต่จะถูก wrap รวมกับ custom conf ที่เพิ่มมาตอน spark-submit เป็น property file
- สั่ง kinit จากคำสั่งที่เราฝังไว้ สำหรับการ authentication
- driver เชื่อมต่อกับ hive metastore ตามที่ config เอาไว้
- driver สร้าง executor แล้วมันก็ transform ตามที่เราสั่งไว้ โดยใช้ connection ที่เราเตรียมไว้จาก hadoop properties ที่เตรียมไว้
น่าจะประมาณนี้ครับ สำหรับใครที่จะต้องทำงานกับ spark on k8s น่าจะลอกท่าตามนี้ได้เลย
สำหรับ PoC ถัดไปที่จะลองคืออยากลอง GitHub - GoogleCloudPlatform/spark-on-k8s-operator: Kubernetes operator for managing the lifecycle of Apache Spark applications on Kubernetes.
แล้วจะมา update เรื่อยๆ ครับ