Arukas でアプリ公開したら運用コスト 0円 でしかも快適だった話

さくらインターネットさんが提供する ”Arukas” という CaaS を利用し、0 円でWebアプリを公開した話です。

個人でちょっとしたWebアプリ作って公開したいけど、クラウドホスティングサービス費用が高いとか、なるべくお金かけたく無いとか・・そういう場合に参考になるかもしれません。

Arukas について

Arukas とは?

Arukas とは さくらインターネットさんが提供する Docker を活用したコンテナベースのホスティング環境です。しばらくベータ版で公開されていましたが、2018年3月26日に、正式サービスとして提供が開始されました。

arukas.io

公式サイトにあった利用料金表です。今回利用させていただくのは冒頭申し上げた通り 0円のコンテナとなります。

f:id:ngzm:20180519175155p:plain

Arukas の特徴

コンテナ関連
  • Docker Hub に PUSH したイメージを PULL + RUN するコンテナ実行環境である
  • Docker Hub のPublicイメージはもちろん、有料版だと Privateイメージも PULL 可能
  • Docker コンテナサービス用に任意のポートを20個まで指定可能
  • Docker Volume は未サポート、データを永続化するには外部の Storage サービス等を別途用意する必要あり
  • Docker Link も未サポート、コンテナ間の連携を行う場合はそれなり工夫が必要
  • 実行中コンテナにアタッチできない、つまり docker exec 相当の機能は未サポート
  • あくまで Docker コンテナ実行環境なので、イメージのビルドとか細かい管理はできない
ネットワーク関連
  • Docker コンテナサービス用ポート番号のうち最初に指定したポートは、エンドポイントとよばれるHTTPSサービスにマッピングされる
  • エンドポイントの実態は HAProxy によるリバースプロキシであり、実際にはロードバランサとして利用可能
  • エンドポイントにぶら下がるコンテナを、手動でスケールアップ、スケールインすることが可能(有料版のみ)
  • コンテナサービス公開用の独自ドメインを任意に設定可能、なおDNS登録は Arukas でないどこかの Name Server で設定する必要がある
コントロールパネルやインターフェース廻り
  • Web画面のコントロールパネルでコンテナ実行、停止、削除、スケーリングとかの操作が可能
  • 有料プランの場合、本画面から簡単にコンテナのスケーリングができる
  • リソースコントロールができる API も利用できるらしい(未検証)
  • 近い将来 CLI で操作できるツールも使えるようになるらしい

Arukas でアプリを公開するまでの道のり

今回公開したWebアプリについて

2018年3月に「アプリ開発で知っておきたい認証技術」というスライドを公開しましたが、この技術的なリファレンスとして作成したデモアプリの動作環境として Arukas を採用しました。ちなみに本アプリは Ruby on Rails で実装しています。

当初は "Scaleway" という格安クラウドサービスを使用していましたが、格安ながら簡単なデモ環境に個人的な費用を費やすのが辛かったのと、、Scaleway 上でも、もともと Docker 上で動かしていたこともあり、Arukas の正式サービス開始に伴い移行しました。

なお、デモサイトはこちらです

AuthsDemo

アプリケーションコンテナイメージを Docker Hub に登録する

Arukas で独自アプリケーションのコンテナを実行するためには、そのアプリケーションの Docker Image を Docker Hub に登録(PUSH)する必要があります。Docker Hub に PUSH するためには、やはりセキュリティ面に配慮する必要があり、最低でもコンテナイメージに秘密情報が混入しないように注意します。

今回は、GoogleFacebookTwitter の認証APIを使用するので、これらの Application ID や Application Secret といったシークレット情報をコンテナイメージに含めない、すなわち config ファイルではなくコンテナ起動時の環境変数で指定できるように改造しました。

Arukas コントロールパネルでアプリケーションコンテナを作成、起動

Docker Hub にアプリケーションイメージを PUSH したら、続いてそのアプリケーションイメージを Arukas に PULL して コンテナを作成し起動させます。

この作業は Arukas のコントロールパネルで行います・・実際のコントロールパネル画面は以下の通りです。特に難しいこともなく、比較的簡単に起動できると思います。

f:id:ngzm:20180524203335p:plain

使ってみてどうだったか?

Scaleway(移行前) と Arukas(移行後) の違い

Scaleway(移行前)

移行前つまり Scaleway の構成は次の通りです。実際よくある Webアプリの構成と思います。

f:id:ngzm:20180523205051p:plain

Scaleway 上に Ubuntu インスタンスを立ち上げ、そこに Docker をインストールし、Ruby on Rails の Docker image をベースとしたアプリケーションコンテナをビルドして起動しています。同時に、リバースプロキシとして nginx コンテナも起動しており、TLS 証明書もしっかり仕込んで HTTPS に対応するなど、アプリケーション以外に色々やることがあります。

Arukas(移行後)

移行後 Arukas における構成は以下のようになりました。

f:id:ngzm:20180523205048p:plain

図で分かりますが、nginxとかによる Reverse Proxy サーバの部分をまるごと Arukas にお任せできるようになった という所が大きな違いで、アプリケーションコンテナだけに自分のリソースを集中できるようになりました。

うれしポイント

1) 無料!

一番うれしいのは、やはりアプリを 無料 で公開できたことです!

2) Webサーバ廻りのケアが不要になる

無料と同じくらいありがたいと思ったのはこれです!!!
Webサーバの構築や管理、すなわちリバースプロキシの構築やTLS証明書の更新などの管理を まるっと Arukas に任せる ことができるようになりました。これは実際問題かなりありがたいポイントです。

3) 意外に快適

0円で利用させてもらっているにも関わらず、意外にも サクサクと動いてくれる のもポイント高いです。今回はデモ用の簡単アプリというのもあるかもしれませんが、それにしても殆どストレスを感じる事なく動作してくれます。

4) 簡単にスケールできる

有料プランであれば、任意にスケールアウト・スケールイン することができます。この機能は Arukas コントロールパネルで手動で操作できます。手動ですが スライダーのつまみを動かすだけですので操作は馬鹿みたいに簡単です。
ただし、例えばセッションの様にステートフルな仕組みを使用したアプリケーションにおいては、スケールアウト時に何らかの問題が発生するかもしれません。

残念ポイント

1) Volume がサポートされていない

個人的には Volume が使えないことが一番残念です。Arukas だけではデータの永続化ができないので、外部に Storage を用意するとかしなければなりません。

2) 実行中の Docker コンテナにアタッチできない

実行中のコンテナにアタッチすることはまだできません。
Volume も使えないため、例えば、走行ログをファイルに出力しても、そのログファイルにアクセスする手段がありません。今回は単なるデモサイトなのでアレですが、本来はきちんと運用方法を確立する必要があります。

3) コンテナリンクが未サポート

もう一つ、コンテナリンクがサポートされていないので、異なる役割を持つ複数のコンテナにより構成されるサービスは、構築しにくいかもしれません。

まとめ

今回のように、簡単なサンプルアプリやデモアプリをさくっと公開したい!という場合には、無料から利用できる とか Webサーバのケアがいらなくなる といったメリットを考えると、大変有難いサービスであると思います。

大きな開発プロジェクトであっても、一部の実験的な機能を試すとか、そういったユースケースで利用できるかもしれません。

個人的には、今回 Arukas を使ってみてかなり満足しています。皆さんも機会があればぜひ試してみてください。

Japan Container days v18.04 に参加しました

前日夜の meetup と当日のセッションを幾つか拝見しました。「コンテナ」技術ってインフラ界隈に限らずアプリ開発の現場でも盛り上がってるなぁ〜と感動しました。

f:id:ngzm:20180422181749j:plain

特に盛り上がりを感じた技術はやっぱし "Kubernates" 。Docker のオーケストレーションは、一時期 Swarm とかもあって混沌としていた感がありましたが、現在では完全に k8s がデファクトですね。今回、サービスの実運用でも活用している事例もちらほら耳にしましたし、この調子でどんどんノウハウも溜まっていくのだろうと思います。

自分が見たセッションのうち幾つかをご紹介

Kubernetes x PaaS  コンテナアプリケーションのNoOpsへの挑戦

@yokawasa さん

CI/CD の効率化がきわめて重要ということで、いろんな塊をまとめて管理できる "Helm" を使えば、例えばロールバックも一気にできてシンプルで便利!なるほどです。

www.slideshare.net

2018年のDocker・Moby

@AkihiroSuda さん

Docker コミッタのお方による、Docker 関連のこれまでの歩みと今後についての話。オーケストレータやランタイムに実際あったバグによるセキュリティ的な課題とか、コミッタさんならではの話が興味深かった。

www.slideshare.net

Kubernetesのない世界 すべてがサーバーレスになる

@yoshidashingo さん & @toricls さん

トークセッションのようなスタイルで、サーバレスの今後についてのセッション。サーバレスを見据えた開発の進め方とか、Observerbility が重要とか、そのためのツールとして例えば "Epsagon" とか "THUNDRA" とかあるよという情報とか、参考になりました。

www.slideshare.net

『コンテナ疲れ』と戦う、k8s・PaaS・Serverlessの活用法!

@jacopen さん

Container 疲れというタイトルから、Serverless 方面の話になるのかな?と思いましたが、そうでもなく、Caas Paas Sererless 何を採用すべきか?というトーンで、目的を明確にして、自分でさわって評価したうえで、潜在的なコストも考慮して、うまく組み合わせて使うのが重要ということで、自分の感覚と近いなぁと思いました。また、Faas はスケールするし、ファンクションが動く時間だけ課金されるのでコスト最適化できやすいが、アプリの作り方が大きく異なるとか、しばらく動いていないとコールド状態となるので、たまに使うと起動が遅いとか、なるほど情報が沢山得られました。あと、読んだ起きたい資料 として "CNCF Serverless Whitepaper" があるそうなので要チェックです。

www.slideshare.net

その他、資料リンク集

次のMediumで Japan Container days v18.04 の資料まとめを作成してくれています。ありがたや。

medium.com

最後に

ここ数年で最も楽しいといっても過言ではないくらい楽しかったです。

WiFi も安定しててちゃんとするところはちゃんとしてたし、前日のビアハッシュでビールとピザ、当日のランチも美味しかったし、何よりスタッフの皆さんが全員やさしく笑顔で対応してくれたのがすごく好印象でした。本当にありがとうございました、そしてお疲れ様でした。

次回は12月に開催されるとのことなので、是非また参加したいです。

認可と認証技術についてのスライドを書きました

認可と認証技術 OAuth 1.0、OAuth 2.0 および OpenID Connect に関するスライドをアップしました。

www.slideshare.net

開発している Web アプリで、OAuth 1.0 や OAuth 2.0 および OpenID Connect の認可と認証技術を組み込んだ時に、あれこれ調査して知り得た技術をまとめたものです。

130ページくらいの力作です!ぜひご覧ください。

デモ

これのデモはこちらにあります

AuthsDemo

デモのソースコードはこちらです。

GitHub - ngzm/auths-demo: This is a demo program with using OAuth 1.0, OAuth 2.0 and OpenID Connect.

モチベーション

認可と認証技術の調査では、関連する仕様が沢山あって、いろいろこんがらがって苦労したこともあり、一度、自分用に整理してまとめておきたかったというのが当初のモチベーションです。

今では、せっかく書いたこともあって、これから認可・認証技術を学びたいという、特にアプリ開発エンジニアの助けになればいいな、という思いが多くなっています。

その他

実は2年前(2016年初旬)にこのスライドを書き始めましたが、当時発生した熊本地震や、母の死去や、会社の事件とかいろいろあって、ずっと執筆できずに中断していたものです。

もう書くのも諦めようかと思っていましたが、今年になってこれらの問題も落ち着いてきたので、何とか完成させることができました。

追記

おかげさまで 2018/03/29 にホットエントリ入りして、多くのエンジニアさんに見てもらうことができました。頑張った甲斐がありました。特に kawasaki.rb のみなさんありがとうございました。

なお、スライドで TLS を TSL と誤記しているとのコメントを数人の方より頂きまして、恥ずかしいので早速スライドを修正したのですが、Slide Share はいつのまにか再アップロードできなくなってしまっているようなのでこのまま公開を継続します。すみません、適宜読み替えていただくようお願いいたします。

nginx サーバの SSL 安全性評価で A+ を獲得

前回の続きです。
前回は、SSL証明書を間違えて設定していた問題を解決した話でした。

ngzm.hateblo.jp

今回は、さらにSSLの安全性評価を A+ にすることが目標です。

参考サイト

SSLの安全性評価を A+ にする方法については、すでに沢山の方がブログなどで発信されていますので、まずは、今回参考にしたサイトを以下にご紹介しておきます。

設定前の評価

設定前の安全性評価は「B」でした。

f:id:ngzm:20180306152936p:plain

特に「Key Exchange」の数値が低く対策が必要な感じです。

設定内容

冒頭でご紹介したサイトを参考にしながら、自分のサイトを A+ にした設定内容を示します。

1) ssl_protocols の設定

nginx の "ssl protocols" で、"sslv3" など脆弱なプロトコルを無効にします。*1

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

2) ssl_ciphers の設定

以下の値で設定します。こちらは httpsだからというだけで安全?調べたら怖くなってきたSSLの話!? - Qiita を参考にしています。

ssl_ciphers ECDHE+RSAGCM:ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:!EXPORT:!DES:!3DES:!MD5:!DSS;
ssl_prefer_server_ciphers on;

3) ssl_dhparam 設定

DH交換鍵の設定。この鍵は、次のOpenSSLコマンドで生成します。生成に結構時間を要します。

$ openssl dhparam 2048 -out dhparam.pem

これを ssl_dhparam に設定します。

ssl_dhparam /etc/nginx/ssl/dhparam.pem;

4) HSTS ヘッダ

このヘッダ情報は、非暗号化の http 通信を抑制するために設定します。このヘッダで 必ず SSL での接続するようにクライアントに指示します。

add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;';

設定後の評価

ここまで設定した結果、安全性評価は無事に「A+」となりました。
なんだかすっきりしました。

f:id:ngzm:20180306183410p:plain

SSLって以外に奥が深いですね。一度基礎からきちんと勉強しておく価値がありそうです。

*1:nginx v1.12 とか v1.13 など最近のバージョンでは、デフォルトで "ssl_protocols TLSv1 TLSv1.1 TLSv1.2" の状態なので、バージョンが v1.12 より新しければ、この設定は特に不要である。

nginx の SSL設定をしくって Facebook アプリ登録でエラーとなった件

現在開発中のアプリを 「Facebook for Developers」でアプリ登録をした際に、SSL (本当はTLSですが、便宜上SSLと表記します)に関するエラーで少々ハマってしまったので、その内容を記録しておこうと思います。なお、SSL をご存知の方にとっては、至極当たり前の結末なので、あくまでも初心者向けということでご容赦ください。

エラー内容

現在開発中のアプリでは、Facebook の「ログイン」サービスを利用しますが、その際に「Facebook for Developers」から自分のアプリを登録する必要があります。

developers.facebook.com

この「Facebook for Developers」では、アプリの様々な設定を行いますが、ログインサービスの利用を一般にオープンにするためには「プライバシーポリシーのURL」というフィールドを設定しなければなりません。早速プライバシーポリシーのページを用意し、このフィールドにURLを登録しようとしたところ、次のエラーが出てしまいました。

Facebook プラットフォームに準拠するものにするには、有効なプライバシーポリソーURLを入力してください。リクエストエラー: SSL Error: Can't validate SSL Certificate. Either it is self-signed (which will cause browser warnings) or it is invalis.

エラーメッセージの特に英語の部分をみると、どうも「SSL証明書がオレオレじゃないの?」とか「じゃなかったら無効な証明書だよ」と言っています。何か SSL の設定が悪いようです。

原因調査

このアプリはウェブアプリで、Webサーバは nginx を使用しています。

SSL証明書は「Let's Encript」で発行したもので、決して「オレオレ証明書」ではありません。また、ChromeFirefox などのブラウザで動かしても、これまでSSLに関連した警告は特に表示されませんでした。*1

SSL サイト安全性チェック

まずは、SSLに着目して調査したところ、SSLのサイトにも安全性が高いもの、低いものがあることがわかりました。そして、それをチェックしてくれる 「Qualys SSL LABS SSL Server Test」というサービスがあるとのこと、ありがたや。

www.ssllabs.com

早速チェックしてみたら「B」評価でした。

f:id:ngzm:20180306140839p:plain

よく見ると「Key Exchange」の部分が黄色表示で問題があります。あと、もうひとつ "This server's certificate chain is incomplete. Grade capped to B." というメッセージがあります。

証明書チェインが不完全?

で、この "This server's certificate chain is incomplete. Grade capped to B." メッセージについて調べると、 This server's certificate chain is incomplete. ... | Qualys Community というコミュニティサイトがヒット、その中に次の投稿がありました。

When user connects to web server, web server sends certificate chain: leaf server certificate and intermediate certificate. What happens leaf certificate is signed by intermediate, intermediate is signed by already in browser stored root certificate, so certification validation is complete and because certificate chain is trusted your leaf server certificate is trusted. When modern browsers receive intermediate certificate they store it in browser cache. Now lets say your server only sends leaf certificate and does not send intermediate certificate (most probably in your case). What will happen? It depends if user has already visited some other web site and retrieved intermediate from that site and store it in browser cache. If it did then browser will use that intermediate certificate from browser cache to validate the chain of trust. But if end user did not visit any other web site using the same intermediate certificate then user will get fatal error in browser like ssllabs displays "incomplete chain".

要するに、SSL 証明書には「leaf server certificate(サーバ証明書)」と「intermediate certificate(中間証明書)」があって、もしブラウザなどクライアントで、中間証明書がキャッシュ含めて入手できないとルート証明書までのチェインが手繰れなくてエラーになります的なことが書いてあります。

ということで、”This server's certificate chain is incomplete. Grade capped to B." というメッセージは、「証明書チェインが不完全ですよ」ということで、もっと意訳すると「中間証明書が無くないすか?」ということではないかと想定されます。

nginx SSL証明書の設定誤りを発見!

これまでの調査を元に、自サイトの nginx の SSL 設定部分を再確認しましたところ、むちゃやばい間違いを発見しました。

ssl_certificate /etc/letsencrypt/live/[my-site-url]/cert.pem;
ssl_certificate_key /etc/letsencrypt/[my-site-url]/privkey.pem;

Let's Encript で SSL 証明書を発行すると、/etc/letsencrypt/live 以下に 4つのファイルができます。

  1. cert.pem
  2. chain.pem
  3. fullchain.pem
  4. privkey.pem

"cert.pem" はサーバ証明書が入ったもの、"chain.pem" は中間証明書、"fullchain.pem" はサーバ証明書と中間証明書が両方入ったもの、"privkey.pem" は証明書と対の秘密鍵です。

nginx の場合、"ssl_certificate" にサーバ証明書、"ssl_certificate_key" に秘密鍵を指定するのですが、中間証明書を設定できるフィールドが用意されていないので、このような場合は "ssl_certificate" にサーバ証明書と中間証明書が両方入った "fullchain.pem" を設定しなければなりません。*2

一方、私のサイトでは、サーバ証明書だけが入った "cert.pem" が設定されており、これでは中間証明書が入手できずにエラーとなってしまうことが判明しました。

対策する

ここまでくると、対策は簡単です。"ssl_certificate" を "fullchain.pem" に変更して、Webサーバを再起動します。

ssl_certificate /etc/letsencrypt/live/[my-site-url]/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/[my-site-url]/privkey.pem;

これで、もういちど「Facebook for Developers」の「プライバシーポリシーのURL」を設定してみます.... と、無事に設定することができました!!
Facebook で発生したエラーは、中間証明書が入手できなかったことが原因であるということで決まりです。

なお、この状態で「Qualys SSL LABS SSL Server Test」で SSLの安全性評価を再実行しました。

f:id:ngzm:20180306152936p:plain

相変わらず「B」評価ですが、”This server's certificate chain is incomplete. Grade capped to B." のメッセージは消えていることが確認できます。

ちなみに「Qualys SSL LABS SSL Server Test」の最高評価は「A+」らしいです。このままだと「Key Exchange」の部分とか問題が残ってますし、せっかくなので、最高評価の A+ を勝ち取るまで nginx と SSL をセットアップしてみたいと思います。

2018年3月7日追記。

最高評価の A+ を勝ち取るまで nginx と SSL をセットアップした内容をブログに書きましたのでリンクしておきます。

ngzm.hateblo.jp

まとめ

  • SSL にも安全性の問題があるので、単にサイトを SSL 化にしただけで安心してはいけない。
  • SSL のサイトを構築した場合は、「Qualys SSL LABS SSL Server Test」などで安全性をチェックしよう。
  • nginx にSSL証明書を設定する場合は、必ず中間証明書とサーバ証明書の両方入っているものを使用すること!間違えたらやばいところ。

以上です。

*1:これは自分が使用しているブラウザのキャッシュに何かのタイミングで必要な中間証明書が残っていたためにたまたま問題が無かっただけということですが...

*2:Apache の場合、2.4.8より前のバージョンでは、サーバ証明書と中間証明書、秘密鍵のそれぞれのフィールドが用意されていたようですが、2.4.8以降は、中間証明書のフィールドが無くなったようなので、nginx と同様 "fullchain.pem" を使用する必要があります。