LoginSignup
3
1

More than 1 year has passed since last update.

SORACOM Arcを使ってAWS LambdaからSORACOMサービスを利用する

Posted at

はじめに

WiFiや有線インターネットからでもSORACOMサービスが利用できるSORACOM Arc、早速使ってみたという記事が続々と出てきていますね。見ていると、実にいろんな環境で動かしています。

(同じ環境と思ったものは最初に見つけたものを紹介しています)

この環境からSORACOM動かせたら面白そう、便利そう、と思われているということですね。
ラズパイやルーター、スマートフォンなどの物理デバイスだけでなく、EC2のような仮想環境、あるいはDockerやCodeBuildのようなコンテナ環境なんかでも動作できてます。WireGuardというVPN技術がネットワークに要求することが少なく、NAT以下のデバイスでも使えるため、比較的簡単に構築できているのもいいですね。

AWS Lambdaでは使えないの?

さて、CodeBuildの記事は私が書いたのですが、本当はAWS Lambdaでやるつもりでした。やっぱりクラウドのいいところである、実行環境を構築・運用せずに処理を実行できるFaaSが使いたいわけです。ただ、実行環境を用意しなくてもいいということは、実行環境が自由にできないということでもあります。VPNを作るためにはネットワークを作成するLinuxの権限が必要なのですがLambdaにはその権限がなく、WireGuardのVPNを作ることができませんでした。そのためLambdaでの実行はいったん諦めました。
(アプリケーションでWireGuardのVPNを実装すればいける可能性はあるけど現実的ではない)

lambda_arc_before.png

その後上のいろいろな記事、特にSORACOM Arcで自宅ネットワークをSORACOMプラットフォームに接続するを読みまして、「SORACOMサービスにルーティングするルーターの下にLambdaの実行環境を入れる」というアイデアを思いつきました。これならLambdaからは特にVPNを作成する必要なく、普通にSORACOMサービスにアクセスできるようになるはずです。

lambda_arc_after.png

この構成を取るためには、SORACOM ArcとのVPN接続を作成し、LambdaからのアクセスをSORACOMプラットフォームのIPアドレスレンジ(100.127.0.0/16)にルーティングするEC2インスタンスが必要です。これはNATインスタンスをちょっと改造すれば良さそうです。それではやってみましょう。

構築

以下の手順で構築します。

  • ネットワーク設定(VPC、インターネットゲートウェイ、サブネット、セキュリティグループ、EIP、ネットワークインタフェース、ルートテーブル)
  • NATインスタンスの立ち上げ
  • NATインスタンスにsoratunインストール、起動
  • NATインスタンスのルーターとしての設定(パケット転送許可、NAPT)
  • Lambda関数の作成・テスト

ネットワーク設定

パブリックなネットワークを手早く作るため、VPCウィザードを使います。

VPCのコンソールのVPCダッシュボード画面にてVPCウィザードを起動します。
image.png

1個のパブリックサブネットを持つVPC(プライベートサブネットを持つVPCを作るとNATゲートウェイが作成されてしまうため)
スクリーンショット 2021-06-27 21.46.38.png

VPCの設定
スクリーンショット 2021-06-27 21.48.39.png

次にプライベートサブネット(Lambdaを動作させるサブネット)とそのルート設定を作ります。
image.png

プライベートサブネットの設定
スクリーンショット 2021-06-27 21.52.40.png

セキュリティグループを作成します。簡単な設定とするため、プライベートサブネットは外向きのみ許可、パブリックサブネットは外向きおよびプライベートサブネットからの通信を全て許可、とします。本番では実使用する通信のみ許可するのが望ましいです。
image.png

プライベートサブネット用
スクリーンショット 2021-06-27 22.07.14.png

パブリックサブネット用
スクリーンショット 2021-06-27 22.09.41.png

NATインスタンスにつけるパブリックIP(EIP)を作成します。
スクリーンショット 2021-06-27 22.40.41.png

スクリーンショット 2021-06-27 22.41.26.png

次にネットワークインターフェースを作ります。NATインスタンスへのルートはNATインスタンスのインスタンスIDを指定することもできるのですが、ネットワークインタフェースにしておくといったんNATインスタンスを落としても再利用できるので便利です。これはVPCではなく、EC2のコンソールにて作成します。
スクリーンショット 2021-06-27 21.56.19.png

ネットワークインタフェースの設定
スクリーンショット 2021-06-27 22.13.21.png

EIPを関連づけます
スクリーンショット 2021-06-27 22.42.57.png

スクリーンショット 2021-06-27 22.45.08.png

送信元/送信先チェックを無効にします。EC2インスタンスをルーター、つまり自分宛ではない通信を取り扱うインスタンスとする場合に必要な設定です。
スクリーンショット 2021-06-27 22.46.04.png

スクリーンショット 2021-06-27 22.47.44.png

次にプライベートサブネット用のルートテーブルを作ります。(パブリックサブネット用はVPCウィザードにて作成されています)
スクリーンショット 2021-06-27 22.16.24.png

ルートテーブルの設定
スクリーンショット 2021-06-27 22.17.15.png

ルートを編集
スクリーンショット 2021-06-27 22.19.07.png

スクリーンショット 2021-06-27 22.19.59.png

ルートテーブルとサブネットの関連付け
スクリーンショット 2021-06-27 22.23.32.png

スクリーンショット 2021-06-27 22.24.22.png

これでネットワーク設定は終わりです。そこそこ面倒なので、CloudFormationなどのIaC(Infrastructure as Code)サービスで作成できるようにしておくと次回以降楽ができます。

NATインスタンスの立ち上げ

NATインスタンスを立ち上げます。
スクリーンショット 2021-06-27 22.28.35.png

AMIはとりあえずAmazon Linux2でいいでしょう。
スクリーンショット 2021-06-27 22.29.19.png

インスタンスタイプはとりあえず最小のt3.nanoとします。NATとして動かす分には十分です。
スクリーンショット 2021-06-27 22.31.07.png

各種設定をします。今回はSystems ManagerのSession Managerという機能を使ってEC2を操作するため、IAM RoleにはAmazonSSMManagedInstanceCoreをポリシーに持つロールを選択します。SSHでログインする場合は、セキュリティグループにて22番ポートを許可する、キーペアを準備して進みましょう。
スクリーンショット 2021-06-27 22.49.25.png

ストレージは特に変えるところはありませんが、今回はストレージが必要ないため、ボリュームタイプをgp3とすると8GBでのIOPSが上がるのでおすすめです。価格は最低性能(といっても3000IOPS。gp2だと最低100IOPSなので30倍)で使う分には安くなります。(詳しくは公式の料金説明をご覧ください)
スクリーンショット 2021-06-27 22.55.14.png

タグは特につける必要がありません
スクリーンショット 2021-06-27 23.05.01.png

セキュリティグループはNATインスタンス用に作成したものを選択します
スクリーンショット 2021-06-27 22.59.40.png

Session Managerでアクセスするため、キーペアなしで作成します
スクリーンショット 2021-06-27 23.01.41.png

これでNATインスタンスの立ち上げは終わりです。ここもできればIaCのテンプレートに入れたいですね。

NATインスタンスにsoratunインストール、起動

NATインスタンスにアクセスするにはSession Managerを使います。EC2のコンソールに統合されたので、そこから入るのがわかりやすいでしょう。
スクリーンショット 2021-06-27 23.12.45.png

正しく設定するとセッションマネージャーの接続ボタンが押せます。押せない場合は、何らかの設定ミスがあります。特にEIPをつけたか、IAM Roleは正しいか、を見直しましょう。
スクリーンショット 2021-06-27 23.13.37.png

これでブラウザからEC2のシェルにログインできます。最初はssm-userという特別なユーザーになっていますが、ここからの作業は権限がいるため、sudoを使ってrootとして実行する必要があります。
スクリーンショット 2021-06-27 23.15.39.png

公式のインストールドキュメントに従ってsoratunをインストールします。
なお、2021/6/27現在において正式にサポートされているのは以下のプラットフォームです。(サポート対象プラットフォームより)

Linux amd64
  Ubuntu 20.04.2 LTS
Linux arm (Raspberry Pi 32-bit)
  Raspberry Pi OS 2021-05-07
  Ubuntu 20.04.2 LTS

Amazon Linux2はサポートされていませんので自己責任です。気になる方はUbuntuを使いましょう。

wget https://github.com/soracom/soratun/releases/download/v1.0.0/soratun_1.0.0_linux_amd64.tar.gz
tar xvf soratun_1.0.0_linux_amd64.tar.gz
cd soratun_1.0.0_linux_amd64
cp soratun /usr/local/bin

これでsoratunコマンドが使えるようになりました。
ブートストラップを実行して、必要な設定ファイルを作成しましょう。
EC2ではSIMを使った認証ができませんので、SAMユーザーを使ったブートストラップを使います。
公式ドキュメントに従ってSAMユーザーを作成し、ブートストラップを実行してください。この後の手順での指定のため、設定ファイルであるarc.jsonは/etc/arc.jsonのパスに作成します。実行すると費用が発生するのでお気をつけください。
(SAMユーザーの作成は省略します)

soratun --config /etc/arc.json bootstrap authkey
Not enough information to bootstrap. Launching wizard.
SORACOM API auth key ID (starts with "keyId-"): **************************************
✔ SORACOM API auth key (starts with "secret-"): ***********************************************************************█
✔ Japan coverage (api.soracom.io)
Virtual subscriber SIM ID: 890000XXXXXXXXXXXXX
Created/updated configuration file: /etc/arc.json

サービスとして動作させるため、以下のようなサービスファイルを作成します。

[Unit]
Description=soratun
Documentation=https://users.soracom.io/
Requires=network-online.target
After=network-online.target

[Service]
Type=simple
# ExecStartPre=/usr/local/bin/soratun bootstrap cellular --config /etc/arc.json
ExecStart=/usr/local/bin/soratun up --config /etc/arc.json
Restart=always
StandardOutput=journal
StandardError=journal
SyslogIdentifier=soratun
SyslogFacility=local7
WatchdogSec=120

[Install]
WantedBy=multi-user.target

これはconf/soratun.service.sampleに入っているので、/etc/systemd/system/soratun.serviceにコピーします。(そのまま使えるように設定ファイルを/etc/arc.jsonとしました)あとはサービスを起動すればOKです。

cp conf/soratun.service.sample /etc/systemd/system/soratun.service
systemctl enable soratun
systemctl start soratun

これでSORACOM Arcの接続は終わりです。SORACOM Airメタデータサービスにアクセスできるかみてみましょう。

curl http://metadata.soracom.io/v1/subscriber
No group ID is specified: 999999XXXXXXXXX

アクセスはできてますね。グループが設定されていないので、メタデータサービスを有効にしたグループを設定しておきましょう。

curl http://metadata.soracom.io/v1/subscriber
{"imsi":"999999XXXXXXXXX","msisdn":null,"ipAddress":null,"operatorId":"OPXXXXXXXXXX","apn":"arc.soracom.io","type":"arc.standard","groupId":"XXXX","createdAt":1624804534104,"lastModifiedAt":1624804960584,"expiredAt":null,"registeredTime":null,"expiryAction":"doNothing","terminationEnabled":true,"status":"active","tags":{},"sessionStatus":{"lastUpdatedAt":1624804534228,"imei":null,"location":null,"ueIpAddress":"XXXX","dnsServers":["0.0.0.0","0.0.0.0"],"online":true,"subscription":"planArc01"},"arcSessionStatus":{"lastUpdatedAt":1624804534228,"arcClientPeerIpAddress":"XXXX","arcClientPeerPublicKey":"XXXX","arcServerPeerPublicKey":"XXXX","arcServerEndpoint":"link.arc.soracom.io:11010","arcAllowedIPs":["100.127.0.0/16"]},"imeiLock":null,"speedClass":"arc.standard","simId":"890000XXXXXXXXXXXXX","moduleType":"virtual","plan":0,"iccid":"890000XXXXXXXXXXXXX","serialNumber":null,"subscription":"planArc01","lastPortMappingCreatedTime":null,"packetCaptureSessions":null,"arcClientPeerPublicKey":"XXXX","lastModifiedTime":1624804960584,"expiryTime":null,"createdTime":1624804534104}

まずEC2でのArcの利用はこれでいいですね。次にルーターとしての設定をします。

NATインスタンスのルーターとしての設定(パケット転送許可、NAPT)

Linuxは初期状態では自分宛でないパケットを転送しません。これを許可するためにカーネルの設定を変更します。

/bin/echo 1 > /proc/sys/net/ipv4/ip_forward
echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf

次にiptablesにて転送の許可、NATの設定をします。まず初期状態を確認します。

iptables -t filter -L --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

Amazon Linux2のデフォルトはINPUT、FORWARD、OUTPUTが全て許可されています。これでいいのか?という気がしないでもないですが、セキュリティグループで防御されている前提なのでしょう。

NAT設定もみてみましょう。

iptables -t nat -L --line-numbers
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination

Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
num  target     prot opt source               destination

こちらもPREROUTING、INPUT、OUTPUT、POSTROUTINGはルールなしで、全て許可されています。
この場合、追加で必要になる設定は、インターネットおよびSORACOMサービスへ通信を中継する際のソースNAPT(MASQUERADE)設定のみです。以下の設定をしましょう。

iptables -t nat -A POSTROUTING -s 10.0.1.0/24 -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 10.0.1.0/24 -o soratun0 -j MASQUERADE

プライベートサブネット(10.0.1.0/24)から届いてeth0にルーティングされるもの、soratun0にルーティングされるものをそれぞれMASQUERADEに指定しています。

この設定を保存するためには、iptables-servicesというパッケージを入れる必要があります。インストールして、saveしておきましょう。再起動時に同じ設定が再現されるはずです。

yum install -y iptables-services
service iptables save

これでルーターとしての設定も終わりました。プライベートサブネットに立ち上げたものであれば、EC2インスタンスだろうがFargateのコンテナだろうが、Lambda関数の実行環境だろうがSORACOMサービスにアクセスできるはずです。試してみましょう。

Lambda関数の作成・テスト

関数の作成をします。
スクリーンショット 2021-06-28 0.21.22.png

関数の設定をします。VPCの設定が必要であることに注意しましょう。ちなみに基本的な権限は通常はCloudWatchLogsへの書き込み権限ですが、VPCの設定がある場合はLambda用ネットワークインタフェースの作成権限がつきます。それ以外の権限は必要ありません。
スクリーンショット 2021-06-28 0.26.15.png

ひとまずメタデータからデータを取得する簡単なコードで確認しましょう。

require 'json'
require 'net/http'
require 'uri'

def lambda_handler(event:, context:)
  puts "Access to SORACOM Air Metadata service."
  uri = URI.parse("http://metadata.soracom.io/v1/subscriber")
  response = Net::HTTP.get_response(uri)
  { code: response.code, body: response.body }
end

Deployボタンを忘れずに
スクリーンショット 2021-06-28 0.33.56.png

実行してみます。
スクリーンショット 2021-06-28 0.34.58.png

あっさり成功しました!準備ができていると楽なんですね。
スクリーンショット 2021-06-28 0.38.34.png

あとは、BeamでWebにアクセスするなり、Funkで他のクラウドの処理を起動するなり、Harvest Dataにメトリクスを送ってLagoonで可視化するなり、Harvest Filesにファイルを保存するなり、色々やってみましょう。

何に使えるの?

Webから取得できる情報をメトリクスとしてHarvest Dataに送ってLagoonで可視化するのが良いのではないかと思います。Lagoonの可視化、アラート機能も強化されたので、収集・可視化のサービスとしては手軽に使えて良いです。Harvest Dataは1日2000回(だいたい1分に1回)までは5円で使えるのですが、これはメトリクスの数によりません。なので複数のメトリクスを1回で送っても1日5円で使えて実はかなりお得です。

また、なんらかのイベントが発生したらLambdaが起動する、という仕組みの場合、Lambdaから呼ばれるサービスはLambdaで個々に対応しないといけないのですが、SORACOMのUnified Endpointとかに送っておけば、そこから連携するサービスは全て使えることになります。自分が手を入れなくても、SORACOMに進化に合わせて対応も広がるでしょう。

色々使い方はあるのではないかと思っています。

おわりに

SORACOM ArcをLambdaで使う方法を考えてみました。(SORACOM Arcの話なのに大半がNATインスタンスの作り方になってしまいました。。)ただ、これがベストというわけではありません。

まずせっかく起動していない時は無料のLambdaなのに、この構成ではNATインスタンスの維持費がかかってしまいます。定常的に処理が発生するならいいですが、ほとんど発生しない時は勿体無いですね。そういう場合は今のところコンテナなどを使う方が良さそうです。

また、SORACOMはデバイスをIMSI(SIMの識別ID)で識別できるという長所があるのですが、この構成だと全てNAT インスタンス内のIMSIになってしまうため、個体識別ができなくなることあげられます。同じLambda関数の、複数の実行環境は同じものとして扱っていいようにも思いますが、複数種類の処理を同じNATインスタンスの下に入れると全部同じになってしまいます。識別したいんだったら関数ごとにサブネットとNATインスタンスを分けないといけないので、構築、運用の負担が大きそうです。

とはいえ、とりあえずできる方法ではあるので、使える方法が広がりました。また、この考えはLambdaだけではなく、他のクラウドやオンプレのシステムでもArcに繋がるルーターを用意すれば同じようにできます。ちょっとSORACOM使ってみたい、という時には試しやすい構成かなと思います。

まだまだ、色々な構成や使い方を考えていきたいですね。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1