まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

タグ:job

IBM Cloud から提供されている Knative ベースのフルマネージドランタイム環境 "Code Engine" を使って cron ライクなスケジュールジョブを実現してみました。


Code Engine については以前にこの環境を使って、コンテナ化されたウェブアプリケーションをデプロイして使う、という内容を紹介したことがあります。準備手順もこの中で紹介していたので、後述の内容に興味を持っていただき、実際に試してみようと感じていただけた場合はこちらのページで紹介する内容も参照し、環境の準備を行っておいてください:
IBM Cloud の新サーバーレス環境 Code Engine を試してみる


今回は上述のリンク先で紹介しているようなウェブアプリケーションではなく、単発実行のスタンドアロンアプリケーション(コマンドラインから指定して実行し、処理が終了したら終わり。GUI なし)を Code Engine で実行できるように設定する方法を紹介します。あわせてこのスタンドアロンアプリを手動で実行するのではなく、cron ライクなフォーマットで実行タイミングをあらかじめ指定しておき、そのタイミングで自動実行させる方法も紹介します。


【ibmcloud CLI のセットアップ】
まず準備段階として ibmcloud CLI をセットアップする必要があります。上述の Code Engine 利用時はコンテナ化されたウェブアプリケーションを Code Engine 上にデプロイする手順を紹介しましたが、この内容であればリンク先のように IBM Cloud のダッシュボード画面を利用した GUI 操作だけで行うことができました。が、今回の内容は現時点のダッシュボード画面からだけでは設定できない内容が含まれており、一部の操作を CLI で行う必要があります(2021年8月8日時点)。そのための ibmcloud CLI のインストールおよびセットアップが必須となります。

ibmcloud CLI のインストールは以下のリンク先を参照し、お使いのシステム(Windows, Linux, MacOS)に合わせたインストールを行ってください:
IBM Cloud CLI の概説


ibmcloud CLI のインストールに続いてセットアップを行います。以下 Windows のコマンドプロンプト環境を使った手順を紹介しますが、基本的にはすべてのシステムでほぼ同様の手順を実行可能です。

まずはコマンドプロンプト画面やターミナルを起動し、ibmcloud CLI を使って IBM Cloud にログインします:
> ibmcloud login -u (ログインID) -g (リソース名:通常は default)

ibmcloud CLI で Code Engine のリソースを操作するには Code Engine 用のプラグインをインストールする必要があります。すでにインストール済みの場合は飛ばしてかまいませんが、まだプラグインをインストールしていなかったり、自信がない場合はログイン後に以下のコマンドを実行して Code Engine プラグインをインストールしてください:
> ibmcloud plugin install code-engine

これで ibmcloud CLI のセットアップは完了しました。


【IBM Code Engine に登録するジョブアプリケーションコンテナを開発】
次に Code Engine にスケジュールジョブとして登録するアプリケーションを開発します。

これはもちろんどのようなアプリケーションでもいいですが、今回は最終的に実行スケジュールを指定して「1時間おきに実行」といった実行を指示することになります。そのためウェブアプリケーションのような常駐型のアプリケーションではなく、実行してそのまま終了するスタンドアロン型のアプリケーションを用意します。アプリケーション自体はどのような言語で作られていてもかまいませんが、x86_64 の Linux で実行できるものを用意してください。

このアプリケーションはご自身で用意していただいてもかまいませんが、一応サンプルを用意・公開しました。以下ではこのアプリケーションを Code Engine 上でスケジュール実行する手順を紹介します:
https://github.com/dotnsf/cejob_sample


Node.js を使ったシンプルなアプリケーションです。メインファイルの内容は以下の実質1行だけで、「実行した瞬間のタイムスタンプを ISO フォーマットで標準出力に表示」するというだけのシンプルなものです:
//. app.js
console.log( ( new Date() ).toISOString() );

Code Engine は Knative ベースということもあり、アプリケーションはコンテナイメージ化されている必要があります。 このアプリケーションをコンテナ化するために、以下のような Dockerfile を用意しています(特にポートを EXPOSE することもなく、単に "$ node app.js" を実行しているだけの Dockerfile です):
# https://nodejs.org/ja/docs/guides/nodejs-docker-webapp/

# base image
FROM node:12-alpine

# working directory
WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

CMD ["node", "app.js"]

作業として必須ではありませんが、自分でもコンテナイメージを作ってみたい場合は docker をインストールして、docker hub にアカウントを作成後に以下のコマンドを実行してイメージをビルドし、docker hub にイメージをプッシュすることで外部から利用可能なコンテナイメージが用意できます(yourname の部分は自分の docker hub アカウント名に置き換えてください):
> docker login

> docker build -t yourname/cejob .

> docker push yourname/cejob


このイメージは私がすでにビルドして公開済みなので、自分でビルドしなくても使える状態になっています:
https://hub.docker.com/r/dotnsf/cejob


以下はこのイメージを使って Code Engine 上で実行できるようにする方法を紹介しますが、自分でビルドしたイメージを使う場合は "dotnsf/cejob" 部分を自分のコンテナイメージ名(上述の "yourname/cejob" 部分)に置き換えて捜査してください。


【IBM Code Engine にジョブを登録】
ここからは実際に Code Engine を使った操作を行います。まずはスケジュール実行させるジョブアプリケーションを Code Engine に登録します。

ウェブブラウザで IBM Cloud にログインします。Code Engine を使うにはライトアカウントでなく、スタンダート以上のアカウントでログインする必要がある点に注意してください。ログイン後の画面で「リソースの作成」ボタンをクリックします:
2021081501


検索バーに "Code Engine" と入力して、Code Engine を選択します:
2021081502


Code Engine に登録するアプリケーションの準備方法を選択します。(docker 環境や docker hub アカウントの準備がなく)ソースコードのみ手元にある場合は右側の「ソース・コードから始める」を選択することで自動的にイメージをビルドして利用することもできますが、今回はすでにイメージが公開されているので、左側の「コンテナー・イメージの実行」の「作成の開始」ボタンを選択します。なお右側の「ソース・コードから始める」の「作成の開始」を選択した場合、コンテナイメージを作ってプライベートリポジトリを利用することになりますが、その際の CPU やメモリ利用量は課金の対象となりますのでご注意ください(既にイメージがある場合は左側から行うことを推奨します):
2021081503


ここからは実際に稼働させるアプリケーションを指定していきます。まずはアプリケーションの種類。以前に紹介したウェブアプリケーションでは「アプリケーション」を選択しましたが、今回のように1回実行して(常駐するでも、待ち受けるでもなく)そのまま終了するアプリケーションの場合は「ジョブ」を選択します。続けてアプリケーションの名前(下図では "mycejob" )を入力します:
2021081504


そのまま下にスクロールして続きを入力します。Code Engine のアプリケーションはプロジェクトという単位でまとめて管理します。すでにあるプロジェクトを選んで使っても(そのプロジェクト内で管理しても)かまいませんが、初めて使う場合はプロジェクトを新規に作成する必要があります。作成する場合は「プロジェクトの作成」ボタンをクリックします:
2021081505


画面右に表示されるダイアログ内で、プロジェクトのサーバーロケーション(下図では「東京」)、プロジェクト名(下図では "my_ce_project")、そしてリソースグループ(下図では「default」、これは選択肢がない場合が多いと思います)を選択して、最後に「作成」ボタンをクリックします:
2021081506


作成したプロジェクトがセレクトボックスに含まれているので選択します。 続けて実行コードを指定します。繰り返しになりますが、今回はソースコードからではなく既存コンテナを使って実行するので「コンテナー・イメージ」を選択し、そのイメージに docker hub 上の dotnsf/cejob を使う場合は "docker.io/dotnsf/cejob" と入力します(自分のイメージを使う場合は該当部分を変更してください):
2021081507


そのまま下にスクロールして更に続きを入力します。ランタイム設定内のインスタンス・リソースでアプリケーションを実行する際の1インスタンスに割り当てられるマシンスペックを指定します(ここで指定するスペックが課金に影響します)。今回は超シンプルなアプリなので最小スペック(vCPU = 0.125 個、メモリ = 0.25 GB)を選択します。他に実行時に環境変数を指定する必要がある場合はここで指定します。最後に右下の「作成」をクリックします:
2021081508


これで Code Engine 上にジョブを作成することができました:
2021081501


この画面を下にスクロールすると、手動でこのジョブを実行することができます。「ジョブの実行依頼」ボタンをクリックして、一度実行させてみます:
2021081502


実行時のインスタンス数を1にして「ジョブの実行依頼」ボタンをクリックします:
2021081503


するとジョブが実行されます(正確にはジョブの実行依頼が実行されます)。この画面が表示された直後はステータスが「待機中」と表示されていて、まだ実行そのものがされていないことを示しています:
2021081504


しばらく待つと(Knative によって)ジョブが実行され、エラーなく正しく実行されていると「成功」ステータスに変わります:
2021081505


先ほどのジョブ一覧画面(ジョブ実行依頼をした画面)に戻ると、実行されたジョブが一覧に含まれる形で表示されていることを確認できます:
2021081506


ここまでの作業で Code Engine 上にスタンドアロンアプリケーションを登録して、手動実行できるようになりました。これだけでもクラウドに実行環境を用意することなく、アプリケーションジョブを(Pay per Use で)実行できる環境が用意できたことになります。この時点でかなり便利な環境ができました。


【IBM CodeEngine に登録したジョブをスケジュール実行する】
本ブログの目的がここです。クラウド上に用意されたアプリケーションジョブを手動実行ではなく、スケジュール実行できるようにします。なお、ここから先の手順は現状 IBM Cloud の GUI ダッシュボードからは行うことができず、CLI で操作する必要があります。

まずは上述の ibmcloud CLI セットアップの手順が済んで、"ibmcloud login" までが完了していることを確認してください。

ジョブにスケジュールを割り当てるには、まず操作する Code Engine プロジェクト(上の例だと "my_ce_project" )を指定する必要があります。ibmcloude CLI で以下のように実行します:
> ibmcloud ce project select --name my_ce_project

確認のため、選択したプロジェクト内のジョブ一覧を表示します(mycejob が存在していることを確認します):
> ibmcloud ce job list

ジョブをリスト中...
OK

名前     経過時間
mycejob  24m

ではこの mycejob を「5分おきに実行」するよう指定します。この「5分おき」というのは cron ジョブスケジュールでは --schedhle "*/5 * * * *" と表現します。またウェブアプリケーションではなくジョブアプリケーソンにこのスケジュールを指定する場合は --destination-type job オプションを指定する必要があります。結論としては以下のように入力します(mycesub という名前の ping サブスクリプションを作成し、mycejob ジョブに対して5分おきの実行を指示しています):
> ibmcloud ce sub ping create --name mycesub  --destination mycejob --destination-type job --schedule "*/5 * * * *"

成功していると5分おきに(毎時 5 分、10 分、15 分、20 分・・・のタイミングで)ジョブが実行され、実行結果が増えていく様子が確認できます:
2021081502


これでインターネットに常時接続している実行環境を用意しなくても、あらかじめ想定したタイミングでスタンドアロンアプリケーションを実行できる環境が用意できました。 COBOL などのレガシー資産でもこういう使い方ができると便利ですよね。


システムプログラマーとして株式会社クーシーに入社後、半年が経ちました。

まだ毎日が勉強で、知らないことも驚くことも多いし、偉そうに感想を言えるような立場ではないのですが、特に大きく印象に残っている発見はこれです:
「今どきのウェブって、これだけの人がこれだけの作業をしてできているのか」

例えば企業のウェブサイト。中小企業だったりするとサイトの規模そのものは必ずしも大きいわけではないのです。極端な例ですが、1ページだけを作る場合で考えます。

これまでの自分がそのページを作ろうとすると、どちらかというと「やりたいことは技術的に実現できるかどうか」を中心に考えていました。今も自分の担当箇所でいえば技術的にできるかどうか、どのくらいでできそうか、ということが検討内容になりますが、それをどう見せるか、についてはあまり重視していませんでした。まあ「jQuery Mobileとか、Bootstrap とか、適当なフレームワークを適当にカスタマイズして使おう。画像は誰か描いて(苦笑)」程度に考えていた、というレベルです。ぶっちゃけ CSS とか基礎はわかっているつもりだけど自分ではサンプルを作る程度でそれ以上にいじることはほとんどない感じ。悪く言えば見た目は軽視してました。

今の会社では UI や UX を専門に担当するチームがあります。PC 用なのか、スマホ用なのか、レスポンシブデザインにするのかを考慮した上で、画像やグラフなどはピクセルレベルで調整して、必要であれば画像のデザインも行った上で HTML をデザインし、CSS を用意してくれます。僕らはその HTML をテンプレートにして組み込んだり、 CSS はロードして指定するだけ。これにバックエンド処理を加えたり、動的な JavaScript を加えたりしてページを作ります。良くも悪くも分業制を敷いて、それぞれのプロが担当する形です。クーシーの強みは(どちらかを外注するとかではなく)その両方のプロが所属しているところだと思います。

これまでの自分の感覚と比べると、軽視していた半分の作業を専門チームがやってくれている、という感じです。作業は細かいし、さすが質も高いし、そして自分は楽です(その代わり作業人月は増えるけど)。自分があまり注力していなかった分野のプロと接する機会がある、というだけでもすごくいい刺激が得られるし、技術を盗む相手という意味でも頼もしい。そして何よりも自分が担当したサイトやサービスがすごく良さげに見える(笑)。

と、そんな当たり前のことが新鮮な状態から自分にとっても当たり前のように感じつつある今日この頃です。


 

このページのトップヘ