heroku 上級編 - Private Space でできること -

Advent Calendar 2018 Heroku 編 22日目、このまま順当にすべて埋まるかどうかは、なんか私にかかっているような気がする今日このごろ、しょっさんです。

本日は、Private Space についてです。無償・クレカアカウントなどで、普段はCommon Runtimeご利用の方の認知率がいかほどか、とても気になるサービスです。Herou Private Space については、以前、Codezineにて「 [Herokuの運用とセキュリティ～HerokuでSSL証明書の自動化とPrivate Spacesでセキュリティを強化しよう](https://codezine.jp/article/detail/10252?p=2)」と題した記事で紹介しています。こちらも合わせてご覧いただければ幸いです。

# Heroku Private Spaces

Heroku Private Spaces の最新情報については[Heroku Private Spaces](https://jp.heroku.com/private-spaces) のWebページでご覧いただけます。今回は、この中からエンジニアのみなさんが飛びつきそうな機能について紹介します。

まず、`Private Space` にすると何が良くなるのでしょうか。一言でいえば、よりセキュアになります。そして、Herokuをより安全に拡張することのできる仕組みがたくさんついています。今日はその中から主な次の機能について説明します。

1. 専用の隔離されたネットワーク
2. マルチリージョン
3. 接続IPアドレスの制御
4. DNS サービスディスカバリ
5. サイト間VPN/Peering
6. Internal Routing

このようにHerokuをよりセキュアなプラットフォームで稼働させることで、オンプレを拡張したクラウドアプリケーション拡張基盤として、大企業での利用にも考慮した安全なネットワークを提供するプラットフォームとして、ご利用いただける代物となってるわけです。

## 1. [専用の隔離されたネットワーク](https://devcenter.heroku.com/articles/private-spaces)

Heroku アプリケーションと、Heroku の提供するデータサービス(Postgres, Redis, Kafka)が、論理的に隔離されたネットワーク内に配置されます。AWS の VPC内に Heroku Dyno とデータサービスが配置される、という仕組みです。

従って、外部からデータベースへは直接アクセスすることができないようになっていたり、Private Space内だけで稼働するような内部用アプリケーションサービスなどの開発も実現できます。

## 2. [マルチリージョン](https://devcenter.heroku.com/articles/private-spaces#private-space-management)

Heroku Common Runtime では、EU/北米の２つのリージョンしか選択ができません。

Private Space を作成いただくことによって、2018年12月22日現在、次の６拠点のリージョンでHerokuのアプリケーションを配置することができるようになっています。

1. 東京
2. バージニア
3. オレゴン
4. フランクフルト
5. シドニー
6. ダブリン

主に日本向けのサービスを展開するようなとき、レイテンシが気になるような場合は東京リージョンを選択すると、低レイテンシでアクセス可能なWebアプリケーションサービスを提供できます。また、複数のリージョンにSpaceを配置して、国をまたいだ災対環境を準備することも可能です。`Heroku Postgres` のフォロワー機能を使えば、異なるリージョンへのデータ同期も、クリックひとつで実現できちゃいます。

## 3. [接続IPアドレスの制御](https://devcenter.heroku.com/articles/private-spaces#trusted-ip-ranges)

隔離されたネットワークだからこそ実現できるとも言えるでしょう。接続元のIPアドレスを制限できます。

特定の社内や企業からだけのアクセスしかさせたくない、開発テスト環境なので、開発者たちからしかアクセスさせたくない、そのようなニーズに応えることができます。

また、`Private Space`にしていただくと、Heroku からのアクセスについて、IPアドレスが４つに固定されます。Heroku アプリケーションから、特定のネットワークへ接続するようなとき、IPアドレスでアクセス制御を行う場合にも、`Private Space` は活躍します。

## 4. [DNS サービスディスカバリ](https://devcenter.heroku.com/articles/dyno-dns-service-discovery)

Common Runtime では、Web Dyno以外の Worker Dynoへダイレクトにアクセスしたいということが実現できません。ですから、非同期アプリケーションとWebアプリケーションを連携させたいようなときは、間に `Redis`などをいれて、キューイングさせたりすることが王道パターンのようになっています。結局、すべてを Web Dynoとして、必要なサービスをすべて Herokuアプリケーションとして公開してしまえば、該当のホスト名へアクセスすればよいわけです。しかし、外部に公開したくないようなサービスだったり、特定の非同期アプリケーションとAPIで連携したいケースは多々あります。

そういったわがままにも柔軟に対応できるのが、`Private Space`のもつ `DNS Service Discovery` です。

`Private Space`内のすべての`Dyno`は、内部的にホスト名を持ちます。どのHerokuアプリケーションの、どのプロセスタイプの、どの`Dyno`まで細かく指定をすることができます。この機能は同一の`Private Space`内だけにはなりますが、外部からアクセスさせたくないサービスや、非同期アプリケーションサービスへの引き渡し、などに対してAPIコールを実現できるすぐれものです。`Private Space`内での `Microservices`もカンタンに実現できてしまう、ということです。

内部アドレスは、次のように定義されています。

内部アドレスのFQDN: **[Dyno番号].<プロセスタイプ>.< Herokuアプリ名>.app.localspace**

例えば、`test-private-space` という名前の Herokuアプリケーション上に、`web`と`worker` Dynoが２つずつ稼働していて、この中の `worker` の１つ目の `Dyno`へアクセスしたい場合であれば、`1.worker.test-private-space.app.localspace` というホスト名へアクセスすれば、該当のアプリケーションへダイレクトに接続することができます。

実際に稼働中の`Dyno`を指定してアクセスできるのはありがた嬉しいのですが、スケールしていて複数の`Dyno`が動いているような場合、わざわざ特定の`Dyno`をアプリケーションで指定するには荷が重すぎます。いくつ動いているかもわからないのに...。

ということで、このFQDNのうち`[Dyno番号]`は省略することができます。`[Dyno番号]`を省略してホスト名解決を行うと、稼働中のプロセスタイプの`Dyno`のうち、ランダムで対象の`Dyno`の３つのIPアドレスが返ってくる仕様です。もちろん３台稼働していなければ、１つや２つしか返ってこないケースもあります。この取得したIPアドレスを元にアクセスすれば、自動的に負荷分散の機能も享受されるという仕組みにもなっています。お便利すぎますね!!

## 5. サイト間[VPN](https://devcenter.heroku.com/articles/private-space-vpn-connection)/[Peering](https://devcenter.heroku.com/articles/private-space-peering)

Heroku Private Spaceでは、オンプレや他のクラウドとセキュアに接続するための方法を２つ、提供しています。

### [Private Space VPN Connections](https://devcenter.heroku.com/articles/private-space-vpn-connection)

Heroku Private Space と Internet VPN を使って、オンプレや他のクラウドとネットワークをセキュアに接続できます。

いくつか制限事項があるので、それらに従っていただく必要はありますが、オンプレのリソース不足を解消するためのオンプレ専用のWebアプリケーションクラウドとして、他のクラウドで使っているリソースと安全に連携させたい、と言ったわんぱくな機能要求に応えることができます。

とくに、`Google Cloud Platform`とはカンタンに接続しやすく、[Site-to-site VPN Connections to Google Cloud Platform](https://devcenter.heroku.com/articles/vpn-private-space-google-cloud-platform)という記事も準備されている程度です。実際に試してみたら、カンタンに実現できましたので、そろそろ手順を公開したいなとは考えてます。

で、従っていただく制約は次のとおりです。

- `Private Space` で定義された`CIDR`と同じネットワークは接続できません (Space作成時に[IPネットワークレンジの変更](https://devcenter.heroku.com/changelog-items/1475が可能なので、これで対処できます)
- BGPは非サポートです。静的ルーティングのみ設定可能です
- 相手側のVPNルータには、公開されたIPアドレスで接続できる必要があります
- VPNプロトコルは、IPsec IKEv1事前共有鍵方式 aes-128-cbc暗号化「のみ」が利用可能です
- Firewall 内のVPNルータへアクセスさせる場合には、4500/udp, 500/udp のポート開放が必要です
- データサービスとのダイレクト接続はできません

### [Private Space Peering](https://devcenter.heroku.com/articles/private-space-peering)

セキュアに相手のネットワークと接続する先が、`Amazon Web Services`の場合、[Private Space Peering](https://devcenter.heroku.com/articles/private-space-peering)の機能が利用可能です。

いわゆる[VPC Peering](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-peering.html)機能をそのまま実装しているだけですが、AWS上の`VPC`とHerokuの`Private Space`を内部的に結合する仕組みです。

基本的には、Herokuアプリケーションから、AWS VPC内のリソースへのアクセスの一方向です。次の`Internal Routing`機能を利用すると、AWS VPC内のサーバから、Herokuアプリケーションへのアクセスが可能になります。

ただし、このサービスも、データベースへのダイレクト接続はできません。ので、あしからず。
Heroku Private Spaceで利用しているデータベースへダイレクト接続したい場合は、[trusted IP whitelisting](https://devcenter.heroku.com/articles/heroku-postgres-and-private-spaces#external-connections)(β)を利用します。現時点では、まだベータサービスとしての提供となっています。

## 6. [Internal Routing](https://devcenter.heroku.com/articles/internal-routing)

前述の`VPN`や`Peering`で接続したネットワークから、Herokuへアクセスしたい! という要望を叶える機能が、この[Internal Routing](https://devcenter.heroku.com/articles/internal-routing)です。

この機能を使ってHerokuアプリケーションを作成すると、内部からのみアクセス可能なIPアドレスが振られる仕組みとなっています。該当のHerokuアプリケーションのホスト名を解決すると、内部ネットワーク経由でHerokuアプリケーションへアクセスする仕組みとなっています。

この`Internal Routing`で作成されたHerokuアプリケーションは、Internetからのアクセスは一切できないものとなっています。ですが、同じ`Private Space`内であれば、前述の[DNS サービスディスカバリ](https://devcenter.heroku.com/articles/dyno-dns-service-discovery)を使ってアクセスすることができます。

# まとめ

すべての機能ではありませんが、特徴的な`Private Space`の機能を紹介しました。今お使いのHerokuアプリケーション、ステップアップしたい、よりセキュアな構成にしたい、クラウドやオンプレ連携を実現したい場合には、ぜひ `Private Space`の利用も検討ください。