Spark history server on k8s with s3 log

Pongthep Vijite
DAMAGeek
Published in
2 min readMay 22, 2021

หมายเหตุ ผู้อ่านสามารถดู table of contents ของ Data Engineering from Noob to Newbie ได้ที่ http://bit.ly/2P7isEw

หลังจากในบทความที่แล้วเราได้ดูกันถึงเรื่องการ submit spark app บน k8s รวมถึงเขียน spark log ไปยัง s3 ในบทความนี้เราจะมาต่อยอดโดยการ set up spark history server กันนะครับ

Spark history server คือ web ui ที่เราสามารถเรียกดูรายละเอียดของ spark job ที่ได้ทำงานเสร็จสิ้นไปแล้วไม่ว่าจะเป็นการดู resource ที่ถูกใช้ในการ process หรือ เวลาที่ใช้ในการประมวลผลของแต่ละ spark function และยังมีอีกหลายแง่มุมที่เราจะสามารถดูได้จาก spark ui เพื่อที่เราจะสามารถนำไปปรับปรุง spark app ของเราให้ทำงานได้ดียิ่งขึ้น

spark history ui
spark ui

docker image ที่เราจะใช้ทำการ deploy spark history นั้นเราสามารถใช้งาน image ที่ได้ทำการ build ไปในบทความก่อนหน้าได้เลย เพราะ spark history ถูก pack มากับ spark lib อยู่แล้ว สิ่งที่เราต้องทำก็คือการสร้าง deployment เพื่อเรียก spark history server ให้ทำงานโดยเราจะสร้าง file ชื่อ spark-history.yaml ซึ่งมีรายละเอียดดังนี้

apiVersion: apps/v1
kind: Deployment
metadata:
name: spark-history-server
namespace: spark-operator
spec:
selector:
matchLabels:
app: spark-history-server
replicas: 1
template:
metadata:
name: spark-history-server
labels:
app: spark-history-server
spec:
containers:
- name: spark-history-server
image: pongthep/spark-k8s-s3:2.0.0
resources:
requests:
memory: "512Mi"
cpu: "100m"
env:
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: aws-s3-secret
key: access
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: aws-s3-secret
key: secret
command:
- /opt/spark/bin/spark-class
- -Dspark.eventLog.enabled=true
- -Dspark.history.fs.logDirectory=s3a://dev.coeffest.com/spark-log
- -Dspark.eventLog.dir=s3a://dev.coeffest.com/spark-log
- -Divy.cache.dir=/tmp
- -Divy.home=/tmp
- org.apache.spark.deploy.history.HistoryServer
ports:
- name: http
protocol: TCP
containerPort: 18080
readinessProbe:
timeoutSeconds: 4
httpGet:
path: /
port: http
livenessProbe:
timeoutSeconds: 4
httpGet:
path: /
port: http

จุด config ที่สำคัญประกอบไปด้วย

  • spec.template.spec.containers.image: ระบุ docker image ที่มีเราได้ทำการ build จาก spark lib
  • spec.template.spec.containers.env: การสร้าง environment variable ภายใน container โดย env var ที่เราจะทำการสร้างนั้นมีอยู่ 2 ตัว นั้นก็คือ AWS_ACCESS_KEY_ID และ AWS_SECRET_ACCESS_KEY เพื่อใช้เก็บ key ในการเข้าใช้งาน aws s3 โดยจะทำการอ่านข้อมูลมาจาก k8s secret ที่ชื่อว่า aws-s3-secret
  • spec.template.spec.containers.comman: เป็นส่วนของ command ที่เราจะทำการเรียก spark history server โดยการ run spark-class และระบุ class เป็น org.apache.spark.deploy.history.HistoryServer ส่วน parameter อื่นๆที่อยู่ระหว่างกลางนั้น เป็นการ override config ใน HistoryServer เพิ่มเติมอย่าง spark.history.fs.logDirectory เพื่อระบุที่อยู่ของ log ใน s3

สำหรับท่านใดที่ต้องการเพิ่มการ assume role ภายใน aws acount สามารถเพิ่มเติม config ดังนี้

- -Dspark.hadoop.fs.s3a.credentialsType=AssumeRole
- -Dspark.hadoop.fs.s3a.aws.credentials.provider=org.apache.hadoop.fs.s3a.auth.AssumedRoleCredentialProvider
- -Dspark.hadoop.fs.s3a.assumed.role.arn="<role.arn>"
- -Dspark.hadoop.fs.s3a.assumed.role.credentials.provider=org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider

ขั้นตอนต่อมาเราจะทำการสร้าง k8s service เพื่อเป็นการ expose pod ของ spark history server ให้สามารถเข้าใช้งาน ui ได้จากการทำ port forward ซึ่งในส่วนของการ config k8s service นี้สามารถระบุต่อท้ายส่วนการทำ deployment ข้างต้นได้เลยแต่ต้องมีเครื่องหมาย — — — ขั้นระหว่าง 2 ส่วน

---
apiVersion: v1
kind: Service
metadata:
name: spark-history-service
namespace: spark-operator
spec:
selector:
app: spark-history-server
ports:
- protocol: TCP
port: 80
targetPort: 18080

แต่ถ้าหาก port forward ดูเป็นยุ่งยากไปสำหรับการใช้งานจริงเรายังสามารถเพื่อเติมส่วนของ k8s ingress ให้สามารถ access ui ได้จากภายนอก k8s cluster ดังนี้

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kafka-history-ingress
namespace: spark-operator
spec:
rules:
- host: "spark-history.coeffest.com" #<-- แปลง domain name ตามที่ได้ config ไว้ใน aws route53 หรือ DNS เจ้าอื่นที่ท่านใช้งานอยู่
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: spark-history-service
port:
number: 80

เมื่อเราทำงาน pack ทุกอย่างเข้าไปใน file spark-history.yaml เรียบร้อย ขั้นตอนสุดท้ายคือการติดตั้งลง k8s

kubectl apply -f spark-history.yaml

สุดท้ายนี้ถ้าท่านใดมีข้อสงสัยหรือคำชี้แนะใดๆสามารถฝากข้อความได้ที่ https://www.facebook.com/coeffest/ นะครับ ขอบคุณมากครับที่ติดตาม

สำหรับคนที่สนใจ Data Engineer สามารถเข้ามาแชร์ข้อมูลกันที่ได้ที่ https://www.facebook.com/groups/369157183664760/

--

--