[Functions] NotificationsとFunctionsで新しくできるようになったこと/What's New With Notifications And Functions?

原文はこちら
https://blogs.oracle.com/developers/whats-new-with-notifications-and-functions

これまでに何度か素晴らしいサービスであるOracle Notification Service(ONS)とOracle Functionsについてブログを書いてきましたが、本日お伝えするのは我らが開発チームの大きな努力によりあなたの人生をもっと楽にするためにこのふたつのサービスに加えられた新機能についてです。以前もCustom URL、PagerDutyとEメールがONSのサブスクリプションに設定できました。また、Oracle Functionsは、Cloud EventsやAPI Gateway、Oracle Integration Cloudからトリガーできました。しかし今回追加された新機能では、このふたつの素晴らしいサービスを組み合わせること、また、サーバレスファンクションをONSの通知トピックにサブスクリプション設定することができるようになったのです。これにより、さまざまなかたちのインテグレーションが可能になったというだけでなく、Oracle Cloud上で利用可能な様々なプロダクトを組み合わせて使ってみる理由が新たにひとつ加わりました。
このふたつのサービスのインテグレーションについて詳しくみていきましょう。以下に挙げる図はドキュメントから抜粋したダイアグラムで、新機能を説明するために手を加えています。ひとつめのダイアグラムは、あるモニタリングメトリックルールがなにがしかの状況を検知して発報したアラームにより、ONSの通知をトリガーするやり方を表しています。
以前であれば、このようなことが起きた場合にオンコールエンジニアであるあなたが朝4時にベッドで起こされることになる通知というのは、あなたのWebサイトが急にバズった結果、多くのトラフィックでボコボコになっているということを意味する知らせだったかもしれません。なるほど確かにそれはいいニュースかもしれませんが、それでもあなたは多大に必要であろう睡眠を諦め、起きてなんらかの対応をしなければなりませんよね。そうやってあなたが眠い目をこすりながら対応するのではなく、必要な対応が自動的に行われるとしたら素敵じゃないですか?まさしくそれをやれるのがファンクションのサブスクリプションなんです。あなたのファンクションがサーバー追加が必要か識別し、OCI SDKを利用して自動化され、スクリプト化されたアクションを実行してくれるんです。
次のダイアグラムは、あなたのサービスやアプリケーションがONSを直接利用することでなんらかのアクションを実行するやり方を表しています。もしかするとあなたは巨大なEコマースアプリケーションがお客様の注文対して受け取り確認のEメールを返信する必要があり、あなたはこのEメールの返信にONSを使おうとしているかもしれません。しかし同時に、あなたは世界初の完全自動化工場も構築しており、お客様の注文に対応するロボットを起動するシーケンスをサーバレスファンクションで実行したいとも思っているかもしれません。そんなことにも対応できちゃうんです!
おことわり:もしかしてサーバレスファンクションで起動されるロボットが働く完全自動化工場というのはちょっとありそうもない話だとお考えかもしれませんが、まあでもユースケースの例としてはわかりやすいと思います。
ここからONSの通知トピックへのファンクションのサブスクリプション方法についてご説明させてください。

"Hello World"サーバレスファンクションの作成

Oracle Functionsをご存知でない場合は、こちらの動画を見てテナンシーのセットアップ方法について学んでください(あるいはこちらにクイックスタートガイドもあります)。

テナンシーの設定が済んだら、"Hello World"のファンクションを作成してデプロイしましょう。今度の動画はあなたの最初のOracle Functionを作成し、デプロイし、起動するやり方を説明してくれます。

最初のファンクションが作成できたら次に進みましょう。

サーバレスファンクションをトリガーするためのサブスクリプションの設定

最初のステップは新しい通知トピックを作成する、または既存のトピックを選択することです。そうしたらトピック詳細のページに行って'Create Subscription'をクリック。
'Protocol'の選択欄で'Function'を選択しましょう。
'Function'プロトコルを選択すると、追加の入力欄が表示されます。起動したいファンクションの所在するコンパートメントと、アプリケーションおよびファンクションIDを選択しましょう。
サブスクリプションが作成されたら、'Publish Message'をクリックしてテストしてみましょう。
なんらかの内容を入力して'Publish'をクリック。
そうしたら選んだファンクションの詳細ページに行き、メトリックを見てそのファンクションが起動されたことを確認しましょう。
ファンクションのObject Storageへのログ出力を有効にしている場合は;
設定したバケットにログが出力されていることも確認できるはずです。
それをダウンロードして見てみると:
というわけでこれがONSの通知でOracle Cloud上のサーバレスファンクションをトリガーする方法でした。他の例やAPIやCLIのドキュメントへのリンクについてはこちらのリリースのお知らせを見てみてくださいね。

[Functions] サーバレスファンクションをNotificationsからトリガーする新機能/Announcing Notifications Triggers for Serverless Functions



Oracle Cloud Infrastructure NotificationsサービスからOracle Functionsをトリガーできるようになりました。

Oracle Functionsはfunctions as a service(FaaS)プラットフォームで、これを使うことで開発者はインフラについて心配することなくビジネス上の要求に見合ったコードを書くことができます。Oracle Functionsが下回りのインフラをマネージし、エラスティックにスケールして受け取ったリクエストをさばきます。Oracle Functionsを使う際にかかる料金は、そのファンクションが実行している間だけのリソースに対してです。
Notificationsはクラウドネイティブなメッセージングサービスで、Eメール、PagerDutyおよびHTTPSエンドポイントに対してのプッシュベースのメッセージングをサポートしてきました。NotificationsはEventsやMonitoringのような他のOracle Cloud Infrastructure 上のサービスとの最上級のインテグレーションを提供します。こうしたインテグレーションを使い、ある通知トピックからイベント通知やアラーム通知をEメールやPagerDutyといった複数のエンドポイントに発出できます。


一般的なユースケース

今日のクラウドが普及した世界では、あなたは自身のサービスが常に利用可能であることを期待するでしょう。クラウドインフラ上で起きた問題を迅速に解決することは、この目標を実現するうえで鍵であり、また、成熟したDevOpsのカルチャーの一部です。あなたがオンコールエンジニアで、あなたのサービスに対して必要なごくシンプルなタスク、例えばコンピュートインスタンスのシェイプにメモリを追加してやるといったようなタスクのために早朝3時に起こされるような場面を想像してみてください。我々はこのようなシナリオを自動化することで、カスタマーエクスペリエンスを向上し、また、お客様がもっと多くの時間を生産的な仕事に使うことができるようになると信じています。Notificationsによってコンピュートインスタンスをリサイズするように書いておいたコードのファンクションをトリガーすることで、このシナリオを自動化することができるんです。
以下はこのインテグレーションによって実現できる、その他のサンプルユースケースです:
  • Monitoringサービスのストレージ使用率メトリックからあがったアラームをきっかけに、Oracle Autonomous Databaseのストレージをスケールアップする
  • Automatic Volume Healingを使い、あるブロックボリューム上の利用率がしきい値を越えたことをきっかけに追加ボリュームを作成し、アタッチすることでボリュームを拡張する。また、その新しいディスク容量の詳細について通知を発出する。
  • サービスやファンクションにカスタムメッセージを発出しつつ、別のファンクションをトリガーする

Diagram that shows creating a function as part of the notifications process.

始めてみよう

Oracle Cloud Infrastructure Notificationsを使っているなら、この新機能はコンソール、SDK、CLIおよびAPIを通じてサブスクリプションを作成するときに利用可能です。以下はいくつかのやり方のサンプルです。

コンソール:トピックへのサブスクリプションの作成

トピックにサブスクリプションを作成する際に、プロトコルタイプとしてFunctionを選んでください。
Screenshot that shows the Create Subscription button on the topic details page in the console.
Screenshot that shows the Create Subscription dialog box with Function selected as the protocol.
トリガーしたいファンクションとそのコンパートメントを選択します。
Screenshot that shows the Create Subscription dialog box with values in the function compartment, function application, and function fields.
サブスクリプションが作成されると、コンソールに表示されます。
Screenshot that shows the subscription details page on the console.

コンソール:アラームの作成

コンソールのMonitoringのページから、Alarm Definitionsをクリックし、Create Alarmをクリック。
Screenshot that shows the Create Alarm button on the alarm definitions page in the console.
アラームの必要情報を入力します。
Screenshot that shows the Create Alarm dialog box with the Define alarm area in focus.
Notificationsの欄では既存のトピックを選択するか、ここから新しくトピックを作成することもできます。
Screenshot that shows the Create Alarm dialog box with the Notifications area in focus and the Create a topic link highlighted.
Screenshot that shows the Create Alarm dialog box with the Notifications area in focus and the Create a new topic and subscription fields highlighted.

CLI

ファンクションのサブスクリプションの作成:
oci ons subscription create \
--compartment-id "<compartment-ocid>" \
--topic-id "<topic-ocid>" \
--protocol "ORACLE_FUNCTIONS" \
--subscription-endpoint "<function_ocid>"

Java SDK

ファンクションのサブスクリプションの作成:
subscription = client.createSubscription(CreateSubscriptionRequest.builder()
                .createSubscriptionDetails(CreateSubscriptionDetails.builder()
                        .compartmentId(compartmentId)
                        .topicId(topicId)
                        .protocol("ORACLE_FUNCTIONS")
                        .endpoint(functionId)
                        .build())
                .build()).getSubscription();

Terraform

Provider Configurationで以下のようにプロトコルを設定します。
variable "subscription_protocol" {
  ...
  default = "ORACLE_FUNCTIONS"
  ...
  ...
}
Oracle_Functionsのタイプでサブスクリプションが作成できます。
resource "oci_ons_subscription" "test_subscription" {
  #Required
  compartment_id = "${var.compartment_OCID}"
  endpoint       = "${var.function_OCID}"
  protocol       = "${var.subscription_protocol}"
  topic_id       = "${oci_ons_notification_topic.test_notification_topic.id}"

  #Optional
  defined_tags  = "${map("${oci_identity_tag_namespace.tag_namespace1.name}.${oci_identity_tag.tag1.name}", "${var.subscription_defined_tags_value}")}"
  freeform_tags = "${var.subscription_freeform_tags}"
}

data "oci_ons_subscriptions" "test_subscriptions" {
  #Required
  compartment_id = "${var.compartment_ocid}"

  #Optional
  topic_id = "${oci_ons_subscription.test_subscription.topic_id}"
}

REST API

ファンクションのサブスクリプションの作成:
POST /20181201/subscriptions
Host: notification.<oracle-cloud-infrastructure-region>.oraclecloud.com
<authorization and other headers>

{
  "topicId": "<topic_OCID>",
  "compartmentId": "<compartment_OCID>",
  "protocol": "ORACLE_FUNCTIONS",
  "endpoint": "<function_OCID>"
}

課金について

Notificationsサービスからファンクションをトリガーするのに追加の料金は必要ありません。Oracle Functionsの課金についてはこちらの製品ページを確認ください。

より詳しい情報

この新機能のより詳しい情報や、Notificationsサービスについて詳しいことを知りたければ以下のリンクをたどってみてください。

[Cloud] Kubernetes CronJobsを使ってOCI CLIコマンドをスケジュール実行/Scheduling OCI CLI commands to run via a Kubernetes CronJob

原文はこちら

このブログポストでは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
RUN wget -qO- -O oci-cli.zip "https://github.com/oracle/oci-cli/releases/download/v${CLI_VERSION}/oci-cli-${CLI_VERSION}.zip" && \
    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
kubectl get jobs --watch
以下のような出力になります:
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>は前述のコマンドの出力から持ってきましょう:
1
kubectl logs <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がサポートしているすべてのサービスのリストはこちらで確認できます。ユースケースはほとんど無限大です!