2015-06-05

postgresql-cf-service-broker を Cloud Foundry で動かす

「Cloud Foundry 百日行」第2回目は,いきなり少し変化球でもうしわけありませんが,postgresql-cf-service-broker です。

基本情報

実はこのアプリは,Cloud Foundry (以下CF) の service broker として機能するアプリで,通常のアプリとは少し異なります。

にもかかわらず,なぜこれを今回紹介するかというと,前回の Kandan の記事 で,このアプリを使って PostgreSQL サービスを構築したので,このタイミングを措いて他にこれを紹介する機会はないと考えたためです。

また,独自に bosh-lite 等を使ってCF環境を構築している/しようとしている方にとっても,本記事は参考になると判断したこともあります。

全体の概要はこんな感じです (© @kenojiri さん; 青色部分は筆者)。

全体の流れは概略以下の様になっています:

  1. Docker コンテナー上の PostgreSQL を起動
  2. postgresql-cf-service-broker をCF上にアプリとしてデプロイ
    環境変数の情報に基づき postgresql-cf-service-broker が PostgreSQL に接続&管理
    postgresql-cf-service-broker をCF環境の service broker として登録&公開
  3. (前記事の例)
    Kandan をCF上にアプリとしてデプロイ
    サービス生成/結合要求に応じてpostgresql-cf-service-broker が PostgreSQL にDB,ユーザー,パスワードを作成
    その情報を含む接続情報を Kandan に渡す
    Kandan はその接続情報を使って PostgreSQL 上のDBにアクセス

では,始めます。上述したように,今回は service broker から使われる PostgreSQL のインスタンスの構築から説明します。

PostgreSQL インスタンスの準備

*既に自由に使える PostgreSQL のインスタンスをお持ちの方は,本節は スキップ していただいてOKです。

今回は検証用ということで,PostgreSQL は Docker を使って用意することにしました。

手順の概要は以下の通りです:

  • 1) Docker のインストール
  • 2) psql (PostgreSQL CLI) のインストール
  • 3) PostgreSQL Docker image の起動

Docker のインストール

CFは Ubuntu 上で動作するので,同じ Ubuntu 上で PostgreSQL Docker image を動かします。まずは Ubuntu に Docker をインストールします。

$ sudo apt-get install -y docker.io

確認:

$ docker --version
Docker version 1.0.1, build 990021a

psql (PostgreSQL CLI) のインストール

$ sudo apt-get install -y postgresql-client

確認:

$ psql --version
psql (PostgreSQL) 9.3.7

PostgreSQL Docker image の起動

Docker Image の取得

今回は,検証時点での最新版 9.4.2 を使うことにしました。

$ sudo docker pull postgres:9.4.2

Docker image の起動

ホストのポート 5432 をコンテナーのポート 5432 に転送し,初期ユーザー cf, 初期ユーザーのパスワードを xxxxxxxx に設定して,取得した Docker Image を起動します。

$ sudo docker run --name cf-postgres -e POSTGRES_PASSWORD=xxxxxxxx -e POSTGRES_USER=cf -e LC_ALL=C.UTF-8 -p 0.0.0.0:5432:5432 -d postgres:9.4.2

接続確認

$ psql -U cf -W -l -h 192.168.xxx.xxx
Password for user cf:
                              List of databases
   Name    |  Owner   | Encoding | Collate |  Ctype  |   Access privileges
-----------+----------+----------+---------+---------+-----------------------
 cf        | postgres | UTF8     | C.UTF-8 | C.UTF-8 |
 postgres  | postgres | UTF8     | C.UTF-8 | C.UTF-8 |
 template0 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
 template1 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
(4 rows)

正しく設定されている場合は,上記コマンドでデータベースの一覧が取得できます。

接続がうまくいかず,以下のようなエラーが出る場合は,

$ psql -U cf -W -l
Password for user cf:
psql: could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

以下のコマンドでポートの listen 状態を確認してみてください。

$ netstat -ltn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:10050           0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:2222          0.0.0.0:*               LISTEN
tcp6       0      0 :::22                   :::*                    LISTEN
tcp6       0      0 :::5432                 :::*                    LISTEN
tcp6       0      0 :::10050                :::*                    LISTEN

ここで,ホストのポート 5432 が IPv6 側しか listen されていない場合,この issue の問題を引いている可能性があります。現状この issue は未解決のようですが,私はここでのやりとりの中に書かれている以下の方法で問題を解決することができました。

現状の確認:

$ sysctl net.ipv6.conf.all.forwarding
net.ipv6.conf.all.forwarding = 0

パラメーターの変更:

$ sudo sysctl net.ipv6.conf.all.forwarding=1
net.ipv6.conf.all.forwarding = 1

修正結果の確認:

$ sysctl net.ipv6.conf.all.forwarding
net.ipv6.conf.all.forwarding = 1

以上で,PostgreSQL インスタンスの準備は完了です。

postgresql-cf-service-broker のデプロイ

次に,postgresql-cf-service-broker をCF上にデプロイしていきます。

以下手順の概要です:

  • 0) デプロイ準備
    • 0.1) JDK, Maven のインストール
    • 0.2) ソースコードの取得&アプリのビルド
    • 0.3) Org, Space の作成
    • 0.4) Application Security Group の解放
  • 1) デプロイ
    • 1.1) アプリのアップロード
    • 1.2) 環境変数の設定
    • 1.3) アプリの起動

順次見ていきましょう。

デプロイ準備

JDK, Maven のインストール

このアプリはJavaのアプリなのですが,CFの標準的なデプロイ方法では,Javaのアプリはコンパイルしてからデプロイすることになっています。そこでまず,Javaアプリのビルドを行うツールを整備します。

【OpenJDK 7】

$ sudo apt-get install openjdk-7-jdk -y

確認:

$ which javac
/usr/bin/javac

【Maven 3】

$ sudo apt-get install maven -y

確認:

$ which mvn
/usr/bin/mvn

ソースコードの取得&アプリのビルド

アプリのソースコードをGitHubからcloneします。

$ git clone https://github.com/cloudfoundry-community/postgresql-cf-service-broker.git

アプリをビルドします。

$ cd postgresql-cf-service-broker
$ mvn package

Org, Space の作成

このアプリをデプロイするための Org と Space を作成します。

アプリを service broker として使う場合,現状ではCFの管理者(admin)権限が必要です。従ってアプリ自体も admin ユーザーとしてデプロイする方が理に適っています。今回は特に,service broker アプリをデプロイするための Org と Space を作ります。既存の Org, Group にこのアプリをデプロイする方は,この操作は必要ありません。

$ cf create-org admin
$ cf create-space svcs

Application Security Group の解放

CFには Application Security Groups という機能があります。これは,アプリから接続できるIPアドレスを制限するもので,bosh-lite のデフォルトでは,アプリはプライベート・アドレス (10..., 192.168..*) には接続できません。

今回構築した PostgreSQL (の Docker Image) は 192.168.. 上に存在するので,そこに接続できるように application security group を設定する必要があります。パブリックIPアドレス上に PostgreSQL のインスタンスを構築した方は,この作業は不要です。

【既存の security group】

$ cf security-groups
Getting security groups as admin
OK

     Name              Organization   Space
#0   public_networks
#1   dns

パブリック・ネットワーク以外は,DNSにしかアクセスできないようになっています。

【security group の作成】

先ほど構築した PostgreSQL インスタンスにアクセスできるルールを持つ application security group を作成します。

まずはルール(JSON形式)を記述したファイルを作成します。

$ emacs postgresql-cf-service-broker.security-groups.json
...
$ cat postgresql-cf-service-broker.security-groups.json
[
    {
    "protocol": "tcp",
    "destination": "192.168.xxx.xxx",
    "ports": "5432" 
    }
]

次に,CF cli を使って,そのルールを持つ application security group をCF環境に登録します。Security group の名前は postgresql-cf-service-broker-security-groups としました。

$ cf create-security-group postgresql-cf-service-broker-security-groups postgresql-cf-service-broker.security-groups.json

確認:

$ cf security-groups
Getting security groups as admin
OK

     Name                                           Organization   Space
#0   public_networks
#1   dns
#2   postgresql-cf-service-broker-security-groups

【Default Running Security Group に bind】

今登録した application security group を Default Running Security Group に bind します。

Default Running Security Group は,全てのアプリの実行(running)時に適用される security group です。この設定をすることで,全てのアプリが,実行時に先ほど作った PostgreSQL インスタンスに接続可能になります。

$ cf bind-running-security-group postgresql-cf-service-broker-security-groups

確認:

$ cf running-security-groups
Acquiring running security groups as 'admin'
OK

public_networks
dns
postgresql-cf-service-broker-security-groups

以上でようやくアプリをデプロイする準備が整いました。

デプロイ

*本節の操作は基本的に https://github.com/cloudfoundry-community/postgresql-cf-service-broker/blob/2e550a065374ffab1a999657c3dabdaa312aa61b/README.md を参考にしました。

アプリの push

CF環境にアプリを登録し,アップロードします。

通常,CFでは,アプリはpushされると自動的に起動されますが,今回のアプリは起動前に環境変数の設定が必要なので,この段階ではまだ起動しません。そのために cf push コマンドで --no-start というオプションを指定します。

また,Java アプリの場合は,ディレクトリーではなく war ファイルをデプロイするので,先ほどのビルドで生成された war ファイルを -p オプションの引数として指定します。

さらに,README では特にアプリのメモリサイズは指定されていませんが,何度か試した結果デフォルトの256MBではメモリが逼迫しそうだったので,メモリサイズを512MBにしました。

$ cf push postgresql-cf-service-broker -p target/postgresql-cf-service-broker-2.3.0-SNAPSHOT.jar -m 512m --no-start

環境変数の設定

README に沿って,アプリの実行環境の環境変数を設定します。

$ cf set-env postgresql-cf-service-broker MASTER_JDBC_URL 'jdbc:postgresql://192.168.xxx.xxx:5432/cf?user=cf&password=xxxxxxxx'
$ cf set-env postgresql-cf-service-broker JAVA_OPTS "-Dsecurity.user.password=xxxxxxxx" 

ここで少し調査が必要だったのは,JDBCのURL形式におけるユーザー名とパスワードの扱いです。 DATABASE_URL (<scheme>://<username>:<password>@<host>:<port>/<database> と異なり,JDBCのURLでは jdbc:<scheme>://<host>:<port>/<dbname>?user=<username>&password=<password> となっていることがわかるまで,しばらく時間が必要でした。

cf. https://devcenter.heroku.com/articles/heroku-postgresql#spring-java

環境変数設定の確認:

$ cf env postgresql-cf-service-broker
Getting env variables for app postgresql-cf-service-broker in org admin / space svcs as admin...
OK

System-Provided:

{
 "VCAP_APPLICATION": {
  "application_name": "postgresql-cf-service-broker",
  "application_uris": [
   "postgresql-cf-service-broker.10.244.0.34.xip.io" 
  ],
  "application_version": "82587e6c-b7c8-410f-bbba-5766d611c4f6",
  "limits": {
   "disk": 1024,
   "fds": 16384,
   "mem": 512
  },
  "name": "postgresql-cf-service-broker",
  "space_id": "a74d2274-c546-49f4-ad38-499df073d499",
  "space_name": "svcs",
  "uris": [
   "postgresql-cf-service-broker.10.244.0.34.xip.io" 
  ],
  "users": null,
  "version": "82587e6c-b7c8-410f-bbba-5766d611c4f6" 
 }
}

User-Provided:
JAVA_OPTS: -Dsecurity.user.password=xxxxxxxx
MASTER_JDBC_URL: jdbc:postgresql://192.168.xxx.xxx:5432/cf?user=cf&password=xxxxxxxx

No running env variables have been set

No staging env variables have been set

アプリの起動

$ cf start postgresql-cf-service-broker
...
requested state: started
instances: 1/1
usage: 512M x 1 instances
urls: postgresql-cf-service-broker.10.244.0.34.xip.io
last uploaded: Mon Jun 1 01:56:13 +0000 2015
stack: lucid64

     state     since                    cpu    memory           disk      details
#0   running   2015-06-01 10:57:57 AM   0.0%   348.9M of 512M   0 of 1G

state が runnning になればOKです。

Service Broker 化

通常のアプリと異なり,動作確認をするためには,アプリの起動後にこれを service broker としてCF環境に認識させる必要があります。

本節の手順の概要は以下の通りです:

  • 1) Service Broker として登録
  • 2) Marketplace に公開

Service Broker として登録

まず,アプリをCFに service broker として登録します。

$ cf create-service-broker postgresql-cf-service-broker user xxxxxxxx http://postgresql-cf-service-broker.10.244.0.34.xip.io

Marketplace に公開

*本節の手順は http://docs.cloudfoundry.org/services/access-control.html を参考にしました。

create-service-broker で登録された service broker は,デフォルトで非公開になっています。従って,この service broker が提供するサービスをCF環境の全ユーザーが使えるようにするには,この service broker のサービス・プランを,サービス名とともに公開する必要があります。

$ cf enable-service-access PostgreSQL -p "Basic PostgreSQL Plan"

確認:

$ cf service-access
Getting service access as admin...
broker: postgresql-cf-service-broker
   service      plan                    access   orgs
   PostgreSQL   Basic PostgreSQL Plan   all
$ cf marketplace
Getting services from marketplace in org nota-ja / space 100 as nota-ja...
OK

service      plans                    description
PostgreSQL   Basic PostgreSQL Plan*   PostgreSQL on shared instance.

* These service plans have an associated cost. Creating a service instance will incur this cost.

TIP:  Use 'cf marketplace -s SERVICE' to view descriptions of individual plans of a given service.

意図した通りに公開されています。なお,このサービス・プランは無料ではないとの警告が出ていますが,今回は検証環境用に自分で構築したサービスなので特に問題はありません。

動作確認

以下,サービスの作成〜実際にアプリと結合しての動作確認については,前回の記事の この箇所 以降をごらんください。

今回使用した環境

(前回 と全く同じです。)