このブログポストではKubernetes CronJobでOracle Cloud InfrastructureのCLIコマンドをスケジュールで定期的に自動的に実行する方法についてご説明します。
例として使うソリューションでは、Oracle Serverless Functionの呼び出しをスケジュール化します。
Kubernetes CronJobsとは
バックグラウンドで様々なタスクをスケジュール実行するのは、開発者、また、運用オペレーターにとってよくあるニーズです。典型的には、"CronJobs"というスケジュール実行方法が知られています。
Kubernetesは
CronJobsをサポートしており、これはKubernetesがタスクをコンテナ化された環境でスケジュール実行するように設定するというものです。この自動化されたジョブは、UNIXやLinuxシステム上でのCronタスクのように実行されます。
Cronジョブは、たとえばバックアップを取ったりメールを送るなどの周期、定期実行されるタスクを作成するのに便利です。Cronジョブはまた、たまにしか行わないようなアクションを指定した時間に一度だけ実行する、というようなことにも使えます。
OCI CLIとは
Oracle Cloud Infrastructure CLIは多機能で簡単に使えるツールで、Oracle Cloud Infrastructureのコンソールと同様の機能を提供している他、コンソールではできない機能もいくつかコマンドとして提供されています。このCLIは開発者にとって、また、GUIよりもコマンドラインインターフェースを好むひとにとって、便利です。
このCLIは多くのOCIサービスの構成やオーケストレーションをサポートしており、コアサービス(ネットワーク、コンピュート、ブロックボリューム)やデータベース、ロードバランシング、サーバレスファンクションなどなどに対応しています。全サポート状況は
こちらのリストをご覧ください。
Oracle Functionsとは
Oracle Functionsはフルマネージドで高いスケーラビリティを備えた、オンデマンドのFunction as a Service(FaaS)プラットフォームです。オープンソースのエンジンであるFnプロジェクトをベースとしてエンタープライズグレードのOracle Cloud Infrastructure上に構築されています。
Oracle Functionsを使って、あなたのコードをデプロイし、それを直接呼び出したりなにかのイベントをトリガーとして起動したりできます。そして費用がかかるのは実行されている時間についてだけです。
Oracle Functionsはコンテナネイティブです。これはすなわち、各ファンクションは完全に自己充足したOCIR Dockerレジストリ上のDockerイメージであり、ファンクションを呼び出したときにプルされ、デプロイされて実行されるということです。
チュートリアルの概要
まず、OCI CLIを含んだコンテナイメージを構築します。その後CLIの設定パラメータと認証情報を格納するKubernetes Secretを構成します。
そしてそのコンテナイメージをOCI Registryにプッシュします。その後、Kubernetes CronJobsでコンテナ化されたOCI CLIコマンドでServerless Functionを呼び出すようにスケジュールを定義します。
事前準備
まず、OCI CLIコマンドをOracle Container Engine for Kubernetes(OKE)上のスケジュール化されたCronJobとして実行するために必要となるコンポーネントの実装と設定を行っていきます。
必要となるのは:
デプロイ手順
1. Kubernetes Secretの設定
この事前準備の前提として、あなたの開発端末にOCI CLIがインストールされ構成されていることが必要です。このプロセスではそのCLI設定ファイルとOCI API秘密鍵の構成が必要になります。
そしてこれらのアーティファクトをKuberenetes Secretの中にコピーしていきます。これはスケジュールされたタスクが実行されるたびに、CLIがあなたのOCIテナンシーにアクセスするのに使われます。
あなたの開発端末から、以下のコマンドを実行しましょう:
1
|
kubectl create secret generic oci-cli-config --from-file=<oci-config-file> --from-file=<rsa-private-key>
|
<oci-config-file>の値と<rsa-private-key>の値はあなたの開発端末の適切なパスに置き換えてくださいね。例えば以下のようになります:
1
|
kubectl create secret generic oci-cli-config --from-file=./.oci/config --from-file=./.oci/ssh/id_rsa_pri.pem
|
OCI CLI設定ファイルとRSA秘密鍵が、コンテナの実行環境ファイルシステム内でパス/root/.ociへ自動的にマウントされます。
これはOCI CLI設定ファイルのデフォルトのファイルシステム格納位置なので、特に設定をしなくてもCLIはスケジュールタスクが起動されるたびにこれらのファイルを使ってあなたのOCIテナンシーに認証をしにいきます。
2. CLIコンテナイメージのビルド
あなたの開発端末でoci-fn-cronというディレクトリを作成し、そこにDockerfileという名前のファイルを以下の内容で作成してください:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
FROM oraclelinux:7-slim
ENV OCI_CLI_SUPPRESS_FILE_PERMISSIONS_WARNING=True
ENV PATH= "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/rh/rh-python36/root/usr/bin:${PATH}"
ENV LC_ALL=en_US.utf8
ENV LANG=en_US.utf8
ARG CLI_VERSION=2.6.14
RUN mkdir /oci-cli
WORKDIR /oci-cli
RUN yum -y install oracle-release-el7 && \
yum -y install oracle-softwarecollection-release-el7 && \
yum-config-manager --enable software_collections && \
yum-config-manager --enable ol7_latest ol7_optional_latest ol7_addons && \
yum-config-manager --disable ol7_ociyum_config && \
yum -y install scl-utils && \
yum -y install rh-python36 && \
yum -y install gcc && \
yum -y install wget && \
yum -y install unzip && \
rm -rf / var /cache/yum
unzip -q oci-cli.zip -d .. && \
rm oci-cli.zip && \
pip3 install oci_cli-*-py2.py3-none-any.whl && \
yes | oci setup autocomplete
ENTRYPOINT [ "/opt/rh/rh-python36/root/usr/bin/oci" ]
|
oci-fn-cronディレクトリに移動し、以下のコマンドを実行してCLIコンテナイメージをビルドしましょう。
1
|
docker build -t oci-fn-cron .
|
3. コンテナイメージをOCIレジストリにプッシュ
次のステップでは、ビルドしたコンテナイメージをクラウドにプッシュします。OCIレジストリサービスの使い方の一連のガイドについては、こちらの記事をチェックしてくださいね。
Oracle Cloud Infrastructureのコンソールにログインしていただく必要があります。また、その際のユーザーは、テナンシーの管理者グループに所属しているか、REPOSITORY_CREATEの権限が付与されたグループに所属している必要があります。
適切な権限があることを確認いただき、ユーザーの認証トークンを生成してください。あとで使うので、このトークンはどこかにコピーしておいてください。
OCIコンソールで、Developer Servies -> Registry(OCIR)タブへと移動し、イメージをプッシュしたいOCIリージョンを選択してください。このリージョンはあなたのOKEクラスターがプロビジョニングされているリージョンと同一のものを選びます。
OCIレジストリへのログイン
あなたの開発端末からdocker loginコマンドでOCIレジストリにログインします。
1
|
docker login <region-key>.ocir.io
|
<region-key>はお使いのOCIリージョンごとのコードを表しています。使用可能なリージョンと対応するコードは
こちらをご覧ください。
プロンプトが出るので、<テナンシー名>/<ユーザー名>のフォーマットでユーザー名を入力します。パスワードのプロンプトが出たら、先程コピーしておいた認証トークンを入力してください。
コンテナイメージのタグ付け
OCIレジストリにプッシュするOCI CLIイメージにタグを付けます。
1
|
docker tag oci-fn-cron:latest <region-code>.ocir.io/<tenancy-name>/oci-cron/oci-fn-cron:latest
|
OCIレジストリへのイメージのプッシュ
docker pushコマンドを使ってコンテナイメージをOCIレジストリにプッシュします。
1
|
docker push <region-code>.ocir.io/<tenancy-name>/oci-cron/oci-fn-cron:latest
|
OCIコンソールから、新たに作成されたリポジトリとイメージが見えるようになっているはずです。
4. Kubernetes CronJobのスケジュール
あなたの開発端末でoci-fn-cron.yamlというの名前のファイルを以下の内容で作成してください:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
kind: CronJob
apiVersion: batch/v1beta1
metadata:
name: oci-functions-cron
spec:
schedule: "*/5 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: oci-functions-cron
image: <region-code>.ocir.io/<tenancy-name>/oci-cron/oci-fn-cron:latest
command: [ "/opt/rh/rh-python36/root/usr/bin/oci" ]
args: [ "--debug" , "fn" , "function" , "invoke" , "--function-id" , "<function-ocid>" , "--file" , "-" , "--body" , "-" ]
imagePullPolicy: Always
volumeMounts:
- name: oci-cli-config
mountPath: "/root/.oci"
readOnly: true
ports:
- containerPort: 9081
restartPolicy: Never
volumes:
- name: oci-cli-config
secret:
secretName: oci-cli-config
items:
- key: config
path: config
- key: id_rsa_pri.pem
path: ssh/id_rsa_pri.pem
|
以下の置き換えが必要です:
- 13行目ではあなたのOCIリージョンコードとテナンシー名
- 15行目では起動したいあなたのOracle FunctionのOCID
ファイルを保存して、以下のコマンドでこのCronJobを送信しましょう:
1
|
kubectl apply -f oci-fn-cron.yaml
|
CronJobオペレーションの確認
以下の手順でCronJobが正しく機能していることを確認できます:
1. ジョブ実行履歴を以下のコマンドで確認:
以下のような出力になります:
1
2
3
4
|
NAME COMPLETIONS DURATION AGE
oci-functions-cron-1575886560 1/1 43s 4m45s
oci-functions-cron-1575886680 1/1 34s 2m44s
oci-functions-cron-1575886800 1/1 35s 44s
|
2. 以下のコマンドでスケジュールジョブに関連したPod名称を取得します。<job-name>は前述のコマンドの出力から持ってきましょう:
1
|
kubectl get pods --selector=job-name=<job-name> --output=jsonpath={.items[*].metadata.name}
|
3. 以下のコマンドで実行されたCLIコマンドのログを取得できます。<pod-name>は前述のコマンドの出力から持ってきましょう:
あなたのファンクションが正しく実行されていれば、以下のような出力になります。これはKuberenetes CronJobとして定義したfn function invokeコマンドをCLIが実行した結果生成されたデータです:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
INFO:oci.base_client.140263433586560: 2019-12-09 21:54:04.502876: Request: GET https:
DEBUG:oci.base_client.140263433586560: 2019-12-09 21:54:04.601030: time elapsed for request 4AFF967835C440009D15F3CFAAC404D2: 0.0978535171598196
DEBUG:oci.base_client.140263433586560: 2019-12-09 21:54:04.601216: time elapsed in response: 0:00:00.092832
DEBUG:oci.base_client.140263433586560: 2019-12-09 21:54:04.601319: Response status: 200
DEBUG:oci.base_client.140263433586560: 2019-12-09 21:54:04.603549: python SDK time elapsed for deserializing: 0.0020453811157494783
DEBUG:oci.base_client.140263433586560: 2019-12-09 21:54:04.603681: Response returned
DEBUG:oci.base_client.140263433586560:time elapsed for request: 0.1009602730628103
INFO:oci.base_client.140263433271056: 2019-12-09 21:54:04.608421: Request: POST https:
DEBUG:oci.base_client.140263433271056: 2019-12-09 21:54:37.288483: time elapsed for request 7C625DE5724D4C3B8E26A771D3F7F87B: 32.679952513892204
DEBUG:oci.base_client.140263433271056: 2019-12-09 21:54:37.288662: time elapsed in response: 0:00:32.676453
DEBUG:oci.base_client.140263433271056: 2019-12-09 21:54:37.288778: Response status: 200
DEBUG:oci.base_client.140263433271056: 2019-12-09 21:54:37.288893: Response returned
DEBUG:oci.base_client.140263433271056:time elapsed for request: 32.68057371187024
|
CronJobスケジュールの変更
Kuberenetesでは、ひとつのCronJobオブジェクトはctontabにおける一行のようなものです。CronJobは
Cronのフォーマットで指定されたスケジュールでジョブを実行します。例として、上の例のCronオブジェクトはOracle Functionを5分ごとに実行します。
違うスケジュールであなたのファンクションを実行するには、単純にあなたのoci-fn-cron.yamlファイルのscheduleの部分を修正し、そのCronJobを再送信すればOKです。
別のCLIオペレーションのスケジュール化
ここでの例では、OCI CLIにOracle Serverless Functionを周期的に実行させました。
ここまでで使い方はわかったと思うので、別のCLIコマンドをKubernetes CronJobsにスケジュール実行させるのはとても簡単でしょう。
別のCronJob定義yamlファイルを作成し、ジョブname(前述のoci-fn-cron.yamlでは4行目)とargs(15行目)のOCI CLIコマンドを要件に応じて修正するだけでOKです。
OCI CLIがサポートしているすべてのサービスのリストは
こちらで確認できます。ユースケースはほとんど無限大です!