如何使用 K8S 自動化定期 CronJob 抓網路公開資料
前言
有使用 Linux 的讀者就知道,若是有定期需要執行的程式就可以 Crontab 把寫好的 script 透過定期的 scheduler 定期執行節省人力。一般常見的使用範疇就是定期更新檔案資料或是網路爬蟲等。今天我們則是要介紹,如何使用 Kubernetes(k8s) 的 CronJob 來自動化抓取網路公開資料(這邊我們使用政府公開資料的雨量資料 JSON 檔案),我們想要的定期執行程式的效果。好的,那就讓我們開始吧!
環境設定
若是對於 Kubernetes(k8s)比較不熟悉的讀者可以想成是 Kubernetes(k8s)是一個大型的 container 調度和管理工具,透過 config 設定可以管理你的 dockerize 後的 application。
在這篇文章中我們會使用 minikube 這個 local 開發測試用的 Kubenetes(k8s)cluster 當作測試 demo 使用。若你的電腦還沒有安裝 Kubernetes(k8s)的相關環境的話,可以先參考官方網站的教學和我們之前的教學文章。
這邊我們使用 macOS 當作範例,需要安裝的有 virtual box、kubernetes-cli 和 minikube 並登入好你的 docker hub 帳戶:
確認一下若是你的 minikube 已經 start 成功,可以使用下列指令確認是否正常啟動:
1 | $ kubectl cluster-info |
另外也可以安裝 kubectx 這個好用小工具,方便你切換到不同 cluster,這邊我們要切換到 minikube。
撰寫 CronJob 程式和 Dockerfile
因為範例為求簡單,這邊我們使用 Python 撰寫一個簡單每分鐘定期抓取政府公開資料的 python 程式,主要功能為:
- 抓取網路公開資料
- 根據時間儲存成 {datatime}.json 檔案到 /data 資料夾下
範例程式 app.py
:
1 | import json |
參考 Dockerfile
:
1 | FROM python:3.7-alpine |
若是完成後可以透過將我們的程式打包成 docker image 然後上傳到 docker hub 上,讓之後的 k8s cronjob 可以抓下來(當然若是私人專案或是公司專案可以考慮使用 google cloud registry 來 host 你的 image)。
打包 image 檔案(xxxx 為你的 docker hub id,k8s-cronjob-pvc-example 為 image 名稱,v1 為 tag 名稱):
1 | docker build -t xxxx/k8s-cronjob-pvc-example:v1 |
若是完成後可以使用 $ docker image list
觀看是否有正常顯示
接著就要推送到 docker hub 上面:
1 | $ docker push xxxx/k8s-cronjob-pvc-example:v1 |
成功後應該就可以在你自己的 docker hub 上面看到上傳的 image 檔案!
撰寫 k8s CronJob config 檔案
上傳 image 到 docker hub 後,我們要開始將我們的程式 deploy 到 minikube 這個 local k8s cluster 上面!
首先我們先定義 schedule 格式為:*/1 * * * *
(每分鐘執行一次)
cron 主要格式 * * * * *
就是由左到右分別為:
- 分鐘
- 小時
- 每月中第幾天
- 月
- 星期幾
若是你對於 cronjob 格式比較不熟悉,可以參考這個網站,他可以透過輸入你的設定值告訴目前格式的效果,十分方便!
以下是參考的 cronjob.yaml
檔案:
- 我們設定 apiVersion 版本和 k8s config 類型 kind 為 CronJob
- 從 kdchang/k8s-cronjob-pvc-example:v1 抓下來我們的程式
- 透過 /bin/sh 指令列印出 ls /data 寫入檔案列表
- 值得注意的是由於 k8s 資源利用的設計,每次 pod 重啟不一定會是在同一個 node 上部屬,另外隨著 pod 的重啟在 local 的檔案生命週期也會隨之消失。這對於定期產生的 pod 完成後就回收的 CronJob 來說會是一個問題:因為我們想要我們定期抓下來的網路資料可以持續存在。關於這個問題我們可以使用寫入資料庫或是宣告 k8s persistent volume 並掛載檔案路徑到 CronJob 中來解決。
以下我們宣告 hostPath volumes 並把 volume mount 到 /data 下面(hostPath 你可以想成若是 pod 重啟,會去找到上次的 pod 的檔案路徑和保留的檔案,當實務上會造成 pod 沒辦法有效 deploy 到適合的 node 上,此處因為使用 minikube 測試所以沒使用 GCP、AWS等 persistent volume 和外掛檔案系統)。
1 | apiVersion: batch/v1beta1 |
接著執行我們的 cronjob.yaml
1 | $ kubectl create -f cronjob.yaml |
此時使用以下指令應該就會看到 cronjob 開始執行
1 | $ kubectl get cronjob |
一分鐘後看到 cronjob pod 成功開始執行!
1 | $ kubectl get pod |
觀看 log
1 | $ kubectl logs -f k8s-cronjob-pvc-example-1561892400-cbpc4 |
若你要移除的話可以使用以下指令:
1 | $ kubectl delete cronjob k8s-cronjob-pvc-example |
總結
以上簡單介紹了如何使用 K8S 自動化定期 CronJob 抓網路公開資料。有許多開發者在從裸機 bare metal server 轉換到 Kubenetes(k8s) 的過程中常常會覺得 deubg 不太習慣,主要原因就是原本可以隨便 ssh 進去主機和抓取最新的資料並重啟機器的簡單粗暴方式變得麻煩,但若是能克服這一點的話,就能享受 dockerize 的可攜性和 k8s 的簡單擴展和部屬特性,更加專注在業務邏輯上。我們下回見囉,掰撲!
參考文件
關於作者:
@kdchang 文藝型開發者,夢想是做出人們想用的產品和辦一所心目中理想的學校。A Starter & Maker. JavaScript, Python & Arduino/Android lover.:)
留言討論