Argo workflows and Why not Airflow?

Neng Liangpornrattana
LINE Developers Thailand
6 min readDec 23, 2019

--

คือตอนนี้ ด้วย project ที่ผมทำงานด้วย ใช้เครื่องมือประเภท Workflow manager ที่ชื่อว่า Argo workflows ครับ (ซึ่งต่อไปจะขอเรียกว่า Argo พอ) เป็นเครื่องมือในการคุม workflow สำหรับ data pipeline ครับ พอสมาชิกในทีมรู้ว่าเลือกเครื่องมือตัวนี้ก็มีคำถามตามมาเลยว่าทำไม?? เพราะตอนแรกเราใช้เครื่องมือที่ชื่อว่า Apache Airflow อยู่(ซึ่งต่อไปจะขอเรียกว่า Airflow พอ) ทำไมถึงไม่เลือกใช้ต่อ??

โพสนี้เลยพยายามจะให้เห็นว่า Argo มันทำงานยังไง ทำไมถึงเลือกเครื่องมือตัวนี้ โดยเทียบกับ Airflow

เอ้า เริ่ม!!

คืองานทาง data engineering เนี่ยครับ จริงๆ มันก็มีขั้นตอนกระบวณการเยอะ แต่ถ้าเอาเฉพาะหลักๆ มันก็มีอยู่ไม่เยอะครับ และที่สำคัญเลยคือ มันจะมี pattern ของขั้นตอนและ pattern นี้จะถูกทำงานซ้ำๆ เช่น ทุกๆ คืน ซึ่งกระบวณการที่มีขั้นตอนชัดเจนเนี่น เราสามารถเรียกมันได้ว่าเป็น workflow

ใน wikipedia ก็นิยามการเป็น workflow ไว้แบบนี้

A workflow consists of an orchestrated and repeatable pattern of activity

ก็เป็นการอธิบายการเป็น workflow ได้ดีอีกเช่นกัน

Flow

เรารู้แล้วว่า work มี flow หรือการไหลจากทีหนึ่งไปที่หนึ่ง แต่มันไหลยังไง???
ลองจินตนาการถึงแม่น้ำ มันก็จะไหลจากต้นน้ำไปยังปลายน้ำ กลางทางมันอาจจะมีแม่น้ำแยกออกมา หรืออาจจะมีแม่น้ำจากสายอื่นไหลมาบรรจบ

Flow

ภาพด้านบนเป็นตัวอย่างของ workflow ครับ รูปแบบการไหลก็จะเป็นอย่าง แยกออกเป็นสองสายเป็นกิ่งของตัวเอง หรือมีการ merge เข้ากิ่งอื่น หรือจากหลายสายมารวมเป็นกิ่งเดียว

แล้วเราจะกำหนดให้แต่ละหน่วยการทำงานให้มีพฤติกรรมตามรูปแบบที่เราอยากให้เป็นได้อย่างไร??

DAG

DAG

จากคำถามด้านบน ตอบได้โดยการ implement flow เราด้วย concept ของ DAG ซึ่ง DAG ย่อมาก

  • Directed — ทิศทาง
  • Acyclic — ไม่ย้อนกลับมาจุดเดิม
  • Graph — ความเชื่อมโยง

จากคุณสมบัติด้านบน จะพบว่ามันคือพฤติกรรมของ flow นั่นเอง

HOW?

เราอยากจะสร้าง workflow ขึ้นมาแล้วจะสร้างยังไง?? ตอนนี้มีเครื่องมือที่ให้เรา implement workflow อยู่หลายตัวมาก เช่น

  • Oozie — เป็นตัวที่มาพร้อมๆ กับ Hadoop เลย เขียน DAG ด้วย XML
  • Luigi — สร้างโดย Spotify เขียน DAG ด้วย Python
  • Azkaban — สร้างโดย Linkedin เขียน DAG ด้วย YAML
  • Airflow — สร้างโดย Airbnb เขียน DAG ด้วย Python

Why not Airflow?

อย่างที่เกริ่นไปด้านบนครับ มีงานที่เรา deploy ไปบน Airflow ก็จริง แต่เราก็มีข้อจำกัดอยู่หลักๆ 3 อย่างนะครับ คือ

  • Time — ข้อจำกัดด้านเวลาครับ ในการขึ้นเครื่องสำหรับ production แล้ว ต้องใช้เครื่อง server ที่มีประสิทธิภาพเลยใช้เวลาในการ provision นานขึ้น
  • Infrastructure — ไม่อยากต้องใช้เครื่องมือเพิ่มขึ้น เพราะ Airflow ต้องการเครื่องมือในการจัดการ state อย่างน้อยๆ 2 ตัวคือ Redis กับ MySQL
  • Maintainability — ซึ่งสาเหตุใหญ่สุดเลยคือเราไม่มีคนคอยดูและสารพัดเครื่องไม้เครื่องมือมากนัก

Why Argo?

แล้วทำไม Argo ถึงแก้ปัญหาได้

  • Container-native for Kubernetes

คือ project นี้ ถูกออกแบบมาให้เป็น container-base อยู่แล้ว และทำงานบน Kubernetes อยู่แล้ว นั่นแปลว่า เราไม่ต้องมีเครื่องหรือเครื่องมือะไรใหม่เลย แค่ติดตั้ง Argo Controller ไปบน Cluster ของ service นี้ก็พร้อมทำงานได้เลย ไม่ต้องมีการดูแลเครื่องมืออะไรเพิ่ม

เรื่อง engineer ที่คอยดูแลก็ไม่ต้องเรียนรู้อะไรใหม่ ถ้าไม่บอกว่าเป็นของๆ Argo เขาก็ไม่ต้องสนใจ สุดท้ายทุก unit การทำงานก็ยังเป็น resource ของ Kubernetes ที่คุ้นเคยอยู่ดี

แค่ปัจจัยนี้ข้อเดียวก็สามารถแก้ปัญหาทั้งสามข้อที่ติดได้เลย

How Argo works?

Argo จะทำงานได้ แค่ติดตั้งตัว controller ตัวเดียวจริงๆ ครับ แค่นี้เลย จากนั้นฝั่ง client ก็แค่ trigger ด้วยคำสั่ง

> argo submit task.yaml

ให้เริ่มทำงานตาม flow ที่ประกาศไว้ในไฟล์ที่ชื่อ task.yaml

จากนั้นสิ่งที่อยู่ข้างใน task.yaml ก็จะไปถูกบันถึงไว้ที่ etcd ซึ่งเป็น storage สำหรับ Kubernetes ทีมี Argo controller คอยดูอยู่ ถ้าหากมีเข้ามา ตัว controller ก็ทำงานตามที่ประกาศไว้ใน task.yaml

ซึ่งในไฟล์ task.yaml นี้ จะเป็น YAML format สิ่งที่อยูข้างในไฟล์นี้ จะเป็นการประกาศ resource ที่ทำให้ Kubernetes เข้าใจว่าจะทำอะไรตาม step บ้าง ซึ่ง resource นี้ เรียกว่า Custom Resource Definition หรือ CRD ซึ่งตัว resource นี้จะถูก declare ว่าเป็นชนิด workflow ที่ custom มาโดยคนที่จะอ่านมันก็คือ Argo controller

หน้าตาของ task.yaml จะประมาณนี้

องค์ประกอบของ CRD ตัวนี้จะประกาศไว้ว่าเป็น

  • ประเภท Workflow
  • generateName เพื่อตั้งชื่อ workflow แต่ generateName มีคุณสมบัติอย่างนึงคือมันจะ generate random key ต่อท้ายไว้ ทำให้ชื่อ workflow เราจะไม่ซ้ำกันในแต่ละครั้งที่ถูกสร้าง
  • บอกจุดเริ่มการทำงานว่าให้ไปเริ่มที่จุด(entrypoint)ที่เรียกว่า whalesay
  • ใน templates จะประกาศ template ของหน่วยการทำงานไว้ หรือเปรียบเทียบง่ายๆ ว่าเป็น function ที่รับ argument ได้ โดย 1 หน่วยการทำงานจะมีการผูกไว้กับ docker image 1 ตัว พอมีการเรียกการทำงาน มันก็จะสร้าง docker container จาก image ที่ประกาศไว้ ละก็ทำงานตามที่เราเขียนไว้ใน image

หลังจากที่ controller อ่าน CRD ตัวนี้แล้ว มันก็จะเริ่มทำงานตามที่เราประกาศไว้ โดยการสร้าง 1 pod ต่อ 1 step การทำงาน พอทำงานเสร็จก็จะ update ไปที่ etcd และ controller ก็จะสั่งให้ทำงานใน step ต่อๆ ไป

ง่ายๆ แค่นี้แหละ ไม่ซับซ้อนเลย

How to define DAG?

DAG จะเป็นตัวกำหนดว่าจะให้ทำอะไรในแต่ละ step ครับ สมมติเราอยากจะทำอะไรบางอย่างเพิ่ม เช่น

  • step A เริ่มทำงาน
  • step B และ C จะเริ่มทำงานหลังจาก step A เสร็จ
  • step D จะเริ่มทำงานหลังจาก step B และ step C ทำงานเสร็จเรียบร้อย

เราจะ define ใน task.yaml เราประมาณนี้

จะใช้ dependencies ในการกำหนดว่าทำอะไรก่อนอะไร

Resubmit

มันจะต้องมีตอน flow ของเราทำงานไม่ผ่านบ้างแหละครับ ตัว Argo เตรียม command ที่ชื่อว่า resubmit ไว้

> argo resubmit --memoized hello-world-5randomletters

จะต้องใส่ชื่อ workflow ที่ถูก generate มาตอน submit โดยมันจะ clone step ที่เสร็จแล้ว แล้วมาแล้วเริ่ม execute step ที่ทำงานไม่ผ่าน ไม่ต้องกลัวว่าจะมีการทำ step ซ้ำแน่นอน

Artifacts

Argo artifacts

มันจะมีกรณีที่เราต้องส่ง state อะไรบางอย่างจาก step อันหนึ่ง ไปยังอีกอันหนึ่ง
Argo มีสิ่งที่เรียกว่า Artifacts หรือเรียกง่ายๆ ว่าเป็น Object storage ที่มีคุณสมบัติสำคัญคือมี S3 compatability ซึ่งเป็น storage ค่ายไหนก็ได้ แค่คุยกันผ่าน protocol ของ S3 ได้ เช่น ตัว S3 เอง หรือ MinIO

ในตอน define DAG ก็เพียงแค่ระบุว่าจะใช้ artifact ที่ path ไหนให้เป็น output ของ step แรก และ path ไหนให้เป็น input ของ step ถัดไป ดูตัวอย่างได้ที่ link ด้านล่างครับ

What about scheduling?

NOTE: ตอนนี้ Argo workflow รองรับการทำ Cron แล้วครับ
ตัวอย่าง: https://github.com/argoproj/argo/blob/master/examples/cron-workflow.yaml
(แก้ไขวันที่ 5 กุมภาพันธ์ 2563)

ถ้าขาด scheduler ไปนี่คงจะเรียกว่าเป็น Workflow manager ได้ไม่เต็มปากเต็มคำนัก แต่ว่า……..

ความตลกของ Argo คือมันไม่มีครับ

แต่บังเอิญว่าผมไปค้นเจอ thread ที่คุยกันเรื่องนี้ เขาอธิบายไว้ประมาณว่า ทีมพัฒนาจะไม่ทำ Scheduler ใน Argo หรอก จะทำซ้ำตัว CronJob ใน Kubernetes ทำไม ถ้าอยากใช้ก็ไปใช้ของ Kubernetes สิ ละก็จบแค่นี้ ไม่มีตัวอย่างให้ดูด้วย ผมก็ดันทุรังเองสิครับ

หลักการง่ายๆ ครับ CronJob ที่เรา define ไว้ มันจะไป trigger ให้สร้าง docker container ที่เรา define ไว้ครับ แปลว่า docker image ของเรา ควรจะมีของ 2 สิ่งคือ ชุดคำสั่งของ Argo และตัวไฟล์ DAG definition ของเรา ถ้าจำเป็นต้องมี configuration อย่างอื่นก็ copy เข้า image ไปใน Dockerfile

ใน cron ของผมจะหน้าตาประมาณนี้

ใน key image ก็จะเป็น image ที่เรา build เอาไว้ ซึ่งผมเจาะให้ entrypoint ใน image รับ params ไว้ด้วย ให้เราสามารถเลือกได้ว่าจะ submit workflow ตัวไหน

Integration & Deployment

หัวข้อนี้เป็นหัวข้อที่ผมใช้เวลากับมันมากที่สุด เพราะแต่ละที่ย่อมใช้เครืองมือไม่เหมือนกัน ท่าในการประกอบร่างก็ไม่เหมือนกัน ซึ่ง project นี้ ใช้ Jenkins เป็นหัวเรือในการทำ integration และ deployment ครับ

หลังจากที่ push code ที่จำเป็นเข้าไปใน git repository ซึ่งผมตั้งใจให้มันเป็น mono-repo นะครับ แปลว่าใน repository นี้จะมี source code ของหลาย pipeline

ในหน้า Jenkins จะมี option ให้เลือกว่าจะ build pipeline ไหน เพราะอยากแยกแต่ละ build version สำหรับแต่ละ pipeline เลย ถ้าต้อง rollback ก็ไม่ต้องไปกังวลว่าจะไปกระทบกับ pipeline อันอื่น

Build step ก็จะเริ่มที่

  • checkout code มาก่อน
  • build ชุด docker image สำหรับ Argo cli กับไฟล์ DAG definition
  • build ชุด docker image สำหรับ unit การทำงานที่ define ไว้ใน DAG ใน templates
  • push 2 images ด้านบนไปยัง docker registry
  • สั่ง apply ตัว K8S CronJob resource เผื่อมีการแก้ไขตาม pipeline ที่เลือกไว้ตอนแรก
  • จากนั้นก็รอมัน trigger ตัว CronJob

Monitoring

หลังจากที่ workflow เราทำงานไปแล้ว เราสามารถดูการทำงานได้ โดย Argo เตรียม web ui ไว้ให้ด้วย

Argo UI

โดยตัว UI จะสรุปตาม step ที่ได้ process ไป และรายละเอียดสำหรับแต่ละ flow และแต่ละ step

อีกหนึ่ง feature ที่ทำได้คือ Exit handler คือหลังจากทำงานจนจบ flow แล้ว ไม่ว่าเสร็จหรือไม่เสร็จ มันจะเข้า Exit handler เสมอ

Exit handler

ตามตัวอย่าง มันจะไปเข้าที่ send-email ก่อนเพื่อส่ง mail จากนั้นก็จะเช็คว่า status เป็นอะไร ถ้า Succeeded ก็จะทำอย่าง ถ้าไม่เป็น Succeeded ก็จะทำอีกอย่างตามที่ define ไว้ใน templates block

Argo VS Airflow

ข้อดี Argo และ Airflow

ทั้งสองเครื่องมือ สามารถทำงานได้ตามจุดประสงค์ที่ต้องการครับ อาจจะมีง่ายบ้างยากบ้าง แต่ก็จบงานจนได้ และยังมี Live UI ที่สามารถแสดงผลและสามารถดูสถานะของ workflow ได้เลย รวมถึงดู Logging ได้ด้วย นอกจากนี้ยังสามารถตั้งเวลาสำหรับ timeout และจะให้ retry ได้กี่ครั้ง

ข้อดี Argo

สามารถทำ Centralized logging ได้ง่ายมาก เพราะ deploy บน Kubernetes ซึ่งถูก implement เรื่องนี้ไว้แล้ว แต่ก็แอบไม่แฟร์กับ Airflow นักเพราะถ้าเอา Airflow มา deploy บน cluster นี้ก็ทำได้เหมือนกัน แต่บังเอิญว่า context ที่เราเปรียบเทียบ เราไม่สามารถ deploy บน cluster ได้

อีกหนึ่งอย่างคือ หน่วยการทำงานเป็น container-base เลยสามารถใช้เครื่องมือหรือภาษาอะไรก็ได้ในการสร้างหน่วยการทำงานนี้

ข้อดี Airflow

เรื่อง Web UI ของ Airflow นี่คือน่าประทับใจสุดครับ มีสรุป DAG และที่ดีที่สุดหลังจากได้ลองใช้ Argo แล้วพบว่าเราสามารถ operate อะไรๆ ผ่าน Web UI ได้เลย ซึ่ง Argo ต้องทำผ่าน CLI เท่านั้น

ข้อเสียของ Argo และ Airflow

ทั้งสองเครื่องมือมีความยากในเรื่อง deployment ครับ แต่ก็มีความยากต่างกันออกไป เช่น ของ Airflow ทุกครั้งที่ deploy จะต้องทำให้ไฟล์ DAG definition ไปอยู่ในเครื่อง worker เพราะ worker ต้องรู้ว่าจะทำงาน step ไหนบ้าง จากไฟล์ DAG definition ที่เป็น Python ซึ่งก็ทำได้ แต่ก็สร้างความยุ่งยากมากขึ้น และยังมีเรื่องอื่นๆ อีก แต่รวมๆ คือ deployment เนี่ย ยังยาก

ในขณะที่ Argo ไม่ต้องปวดหัวกับเรื่อง deploy ไฟล์ DAG definition ไปยังเครื่อง worker เพราะกลไกของ Kubernetes จัดการตรงนี้ให้ แต่กลายเป็นว่าความปวดหัวจะไปอยู่ที่การวิธีการ build docker image มากกว่า และก็เนื่องจากมันยังใหม่ ก็เลยยังไม่มี practice ที่น่าจะเดินตาม ก็ต้องมาลองผิดลองถูกกันนานมาก

ข้อเสีย Argo

ตัว Argo ตาม concept มันไม่ยากเลยครับ แต่การที่ต้อง deploy บน Kubernetes ต่างหากที่เป็นเรื่องยาก เพราะต้องเข้าใจหลายๆ เรื่องของ Kubernetes ก่อนครับ รวมถึงของมันก็ยังใหม่ ยังมี bug มีปัญหาหลายอย่าง ต้องมีท่าแก้ปัญหาชั่วคราวแปะๆ เข้าไปเยอะ ยังไม่ค่อยนิ่งเท่าไหร่ และอย่างที่เกริ่นไปในเรื่อง UI คือเราไม่สามารถ operate อะไรๆ บน UI ของ Argo ได้

ข้อเสีย Airflow

คือต้องใช้ Python เท่านั้นครับ

สรุป

ตัว Argo เองก็สามารถแก้ปัญหาใน context ของ project ที่ผมทำงานได้อยู่ ส่วน Airflow เองก็ไม่ได้แย่อะไรในด้าน functionality แต่แค่การ deployment มันยังไม่พอดีกับ context นี้ครับ ในการทำงานจริงๆ คงจะไม่ได้ dedicate ไปเลยว่า project นี้ จะต้องใช้ Argo อย่างเดียว ก็คงจะเลือกใช้ตามความเหมาะสม

สำหรับท่านใด อยากจะศึกษาก็เริ่มที่ link ด้านล่างเลยครับ

--

--

Neng Liangpornrattana
LINE Developers Thailand

A data plumber, basketballer, workout addicted, dog and cat lover