概要
AWS LambdaがCOBOLをサポートすると発表し、バズった時からかなり遅れていますが、Lambdaを扱う機会があったため、概要をまとめたいとおもいます。
公式でサポートすると発表されていたCOBOLについては、Lambdaの一般メニューからは選択できず、サポート元のBluAge社に問い合わせないと使えないようなので、先人の知恵を借りて、カスタムランタイムとレイヤーを利用した構築を行います。
今回は、Open COBOLの日本語対応版であるopensource COBOLを利用します。
COBOLビルド環境
COBOLのビルド環境の作成ですが、オープンCOBOLソリューション部会のdocker hubにてイメージを作成しているため、そちらを利用します。
Lambdaレイヤーの作成
まずはAWS Lambdaのレイヤーを作成する必要があります。
レイヤーの作成には、必要なライブラリを集めてアップロードする必要があります。
ビルドしたCOBOLアプリケーションに対し、lddコマンドで依存性を確認して必要なファイルを選定します。
[root@2a4317c788de /]# ldd lambda/cobol/hello.so
linux-vdso.so.1 => (0x00007fff3b5fd000)
libcob.so.1 => not found
libm.so.6 => /lib64/libm.so.6 (0x00007f79179a0000)
libvbisam.so.1 => not found
libgmp.so.10 => /lib64/libgmp.so.10 (0x00007f7917728000)
libncurses.so.5 => /lib64/libncurses.so.5 (0x00007f7917501000)
libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007f79172d7000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f79170d3000)
libc.so.6 => /lib64/libc.so.6 (0x00007f7916d06000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7917ea5000)
上記のファイル群をlib
に、コンパイラと実行用ファイルであるcobc
およびcobcru
をbinに格納し、レイヤーとしてアップロードします。
Lambda関数の作成
bootstrapの作成
カスタムランタイムを利用しているため、bootstrapを公式のサンプルをもとに編集します。
#!/bin/sh
set -euo pipefail
# Handler format: <cobol program id>.<dummy>
#
# The script file <cobol program id> must be located at the root of your
# function's deployment package, alongside this bootstrap executable.
while true
do
# Request the next event from the Lambda runtime
HEADERS="$(mktemp)"
EVENT_DATA=$(curl -v -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
INVOCATION_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)
# Execute the COBOL function
RESPONSE=$(echo $EVENT_DATA | cobcrun $(echo $_HANDLER | cut -d. -f1))
# Send the response to Lambda runtime
curl -v -sS -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$INVOCATION_ID/response" -d "$RESPONSE"
done
ここではRESPONSE=
部分を修正し、cobcrun
にてCOBOLアプリケーションを呼び出すようにしています。
$_HANDLER
はLambdaの関数で設定する関数名のようなもの。ここではhello.handler
が入力される想定としています。
COBOLプログラム
今回の検証では、実行してレスポンスを返すだけのCOBOLプログラムを作成します。
レスポンス内容は公式サンプルのスクリプトを参考にしています。
また、入力されたEVENT_DATA
が扱えるよう、標準入力を読み込むようにしています。
******************************************************************
* opensource COBOL and AWS Lambda sample program
******************************************************************
IDENTIFICATION DIVISION.
******************************************************************
PROGRAM-ID. hello.
AUTHOR. nor51010.
DATE-WRITTEN. 2019-06-11.
******************************************************************
ENVIRONMENT DIVISION.
******************************************************************
INPUT-OUTPUT SECTION.
FILE-CONTROL.
******************************************************************
DATA DIVISION.
******************************************************************
FILE SECTION.
******************************************************************
WORKING-STORAGE SECTION.
01 HELLO-STR PIC X(256).
01 ACCEPT-STR PIC X(128).
01 SPACE-IDX PIC 9(005).
******************************************************************
PROCEDURE DIVISION.
******************************************************************
MAIN-RTN.
STRING '{"statusCode": 200, ' DELIMITED BY SIZE
'"body": "Hello from opensource COBOL!", '
DELIMITED BY SIZE
'"input": [;' DELIMITED BY SIZE
INTO HELLO-STR.
MAIN-001.
ACCEPT ACCEPT-STR FROM CONSOLE.
PERFORM VARYING SPACE-IDX FROM FUNCTION LENGTH(ACCEPT-STR)
BY -1
UNTIL SPACE-IDX = 0
IF ACCEPT-STR(SPACE-IDX:) NOT = SPACE
EXIT PERFORM
END-IF
END-PERFORM.
STRING HELLO-STR DELIMITED BY ";"
ACCEPT-STR(1:SPACE-IDX) DELIMITED BY SIZE
';' DELIMITED BY SIZE
INTO HELLO-STR.
MAIN-002.
STRING HELLO-STR DELIMITED BY ";"
']}' DELIMITED BY SIZE
INTO HELLO-STR.
DISPLAY HELLO-STR.
MAIN-EXT.
STOP RUN.
ビルド
Dockerfileを利用して、一括でビルドできるようにします。
以下、今回使用したDockerfileとビルド用のスクリプトです。
dockerhubからイメージを取得し、必要なライブラリをlambda-oss-cobol-layer.zip
に、関数用のスクリプトとCOBOLアプリケーションをlambda-oss-cobol-hello.zip
にまとめます。
FROM opensourcecobol/opensource-cobol
# add zip command
RUN yum install -y zip
# create lambda layer
RUN mkdir -p /lambda/layer/lib
RUN mkdir -p /lambda/layer/bin
RUN cp /usr/lib/libcob.so.1 \
/usr/lib/libvbisam.so.1 \
/lib64/libm.so.6 \
/usr/lib64/libgmp.so.10 \
/lib64/libncurses.so.5 \
/lib64/libtinfo.so.5 \
/lib64/libdl.so.2 \
/lib64/libc.so.6 \
/lib64/ld-linux-x86-64.so.2 \
/lambda/layer/lib
RUN cp /usr/bin/cobc \
/usr/bin/cobcrun \
/lambda/layer/bin
RUN cd /lambda/layer && zip -r /lambda-oss-cobol-layer.zip ./lib ./bin
# create lambda function
RUN mkdir -p /lambda/cobol
COPY bootstrap /lambda/cobol
COPY hello.cbl /lambda/cobol
RUN cd /lambda/cobol && cobc hello.cbl
RUN cd /lambda/cobol && zip /lambda-oss-cobol-hello.zip ./bootstrap ./hello.sh ./hello.so
WORKDIR /
ENTRYPOINT [""]
#!/bin/bash
docker build -t lambda-oss-cobol:latest .
docker run -it --rm -v `pwd`:/tmp lambda-oss-cobol cp /lambda-oss-cobol-hello.zip /lambda-oss-cobol-layer.zip /tmp/
AWSへの適用
レイヤー登録
先ほど作成したZIPファイルからレイヤーを作成します。AWS Lambdaのコンソールからレイヤーの作成にすすみ、ZIPファイルをアップロードします。
アップロードが完了すると、Layer画面に表示されるため、ここのバージョンARNをメモしておきます。
関数の作成
引き続き関数の作成を行っていきます。一から作成でランタイムを、「ユーザー独自のブートストラップを提供する」にします。アクセス権限は必要に応じて設定してください。
関数ができたらレイヤーの追加を行います。DesignerのLayersを選択し、レイヤーの追加を行います。
レイヤーの追加では、先ほどメモしたバージョンARNを入力して追加します。
続いて、関数コードをアップロードします。Designerの関数名を選択し、コードエントリタイプで「.zipファイルをアップロード」を選択し、先ほど作成したlambda-oss-cobol-hello.zip
をアップロードします。
動作確認
テストを利用して、動作確認を行います。新しいテストイベントを作成します。今回はテンプレートの「Hello World」を利用します。
作成したテストを実行すると、レスポンスが確認できます。
実行結果から、opensource COBOLがLambda上で動作し、引数としてイベント情報のJSONを読み込めていることがわかります。
まとめ
AWS Lambdaのカスタムランタイムを利用することで、容易にopensource COBOLのCOBOLアプリケーションをサーバーレス化することができました。
作りこまれている業務ロジックの一部をマイクロサービス化し、新しい基盤システムと連携するなどといった活用が見込まれます。
参考資料
opensource COBOLの提供元とか参考にしたサイトなど
今回作成したファイルはgithubで公開しています。
https://github.com/nor51010/lambda-oss-cobol