やりたいこと
OKE でも OCI Compute 上の minikube でもいいので、とにかく Oracle Cloud 内にある Kubernetes クラスタから CronJob を使って OCI Functions をスケジュール実行したい!
方針
-
OCI CLIコンテナ・イメージ を使って CronJob から function を起動する
function を起動するためのイメージを自作するのは面倒なのでこれを使います。 -
インスタンス・プリンシパル 認可を使う
OCI CLI では--auth instance_principalで有効化できます。
そして、動的グループを作成し、さらに適切なポリシーを設定して、CronJob (がデプロイされている K8s が稼働しているコンピュート・インスタンス) から function を起動します。
手順
動的グループを作成する
CronJob が実行されるコンピュートを動的グループに含めます。
-
シンプルに特定のインスタンスを指定する場合
ALL {instance.id = '<instance-ocid>'}* -
特定のコンパートメント内の全インスタンスを指定する場合
ALL {instance.compartment.id = '<compartment-ocid>'}* -
それじゃ広すぎるだろうという場合は、インスタンスにタグをつけておいて、タグの値で範囲を限定することができます。OKEクラスタのワーカーノードなど複数インスタンスを指定する場合、IDでなくタグで指定が可能です。
All {instance.compartment.id = '<compartment_ocid>', tag.<tagnamespace>.<tagkey>.value='<tagvalue>'}
* 正確には ALL {} は不要です
ポリシーを作成する
とりあえずは
allow dynamic-group <動的グループ名> to use functions-family in tenancy
で function を起動できます。
細かな制御を行いたい場合は 「ファンクションを呼び出して管理するためのアクセス権の制御」 を参照して下さい。
CronJob のマニフェストを作成する
こんな感じです。
apiVersion: batch/v1
kind: CronJob
metadata:
name: functions-cronjob
spec:
schedule: "*/3 * * * *" # この例では3分おきに
timeZone: "Asia/Tokyo" # 指定しないと UTC になっている場合があるので注意
concurrencyPolicy: Forbid # Allow / Replace
jobTemplate:
spec:
template:
spec:
containers:
- name: invoke-function
image: ghcr.io/oracle/oci-cli:latest # OCI CLIコンテナ・イメージ
imagePullPolicy: IfNotPresent
args:
- "--auth"
- "instance_principal" # インスタンスプリンシパルを使う
- "fn"
- "function"
- "invoke"
- "--function-id"
- "ocid1.fnfunc.oc1........" # function の OCID
- "--body"
- "{}" # function に渡す任意のインプット情報
- "--file"
- "-" # アウトプットは標準出力に
restartPolicy: Never # Always / OnFailure
K8s で CronJob を実行する
kubectl apply -f <manifest-file> して下さい。
まとめ
バッチジョブ自体は無償利用枠の大きな OCI Functions で稼働させて、ジョブ制御を K8s (Job / CronJob / Argo Workflows などなど) で実現するってどうですか?(注: OCI Functions には実行時間制限あり)
OCI Data Flow のスケジュール実行とかにも応用できますね。
追記
CronJob から呼び出された Function が、さらに他の OCI のリソースにアクセスする場合、この Function に対する認可(リソース・プリンシパル等)を考慮しないといけませんのでご注意を。