踏み台サーバ経由でのHBase on Amazon EMRへのアクセス

[フューチャーアーキテクト Advent Calendar 2017](https://qiita.com/advent-calendar/2017/future)の4日目です。

## 前提
* AWSのPrivate SubnetでHBase on EMRを構築
* クライアントPCのHBaseクライアントで、踏み台サーバ(Bastion Server)経由でHBaseにアクセスを行いたい

![](https://qiita-image-store.s3.amazonaws.com/0/102882/4ecb2e5b-104f-5850-a3e1-13f5b56aad40.png)

### サーバ接続情報例
|       サーバ        | public IP | private IP |                  private DNS                  |
| ------------------- | --------: | ---------: | --------------------------------------------- |
| 踏み台サーバ        |   1.2.3.4 | 172.16.1.2 | -                                             |
| HBase(Master)       |         - | 172.16.2.3 | ip-172-16-2-3.ap-northeast-1.compute.internal |
| HBase(RegionServer) |         - | 172.16.2.4 | ip-172-16-2-4.ap-northeast-1.compute.internal |

### 確認環境
* クライアントOS
    * Windows7 64bit
* SSHクライアント
    * PuTTY
* HBaseクラスタ
    * EMR 5.4.0 (Master1台、RegionServer1台)
* HBaseクライアント
    * [gohbase](https://github.com/tsuna/gohbase) (master branch)

## 課題点・実現方法
1. HBaseの踏み台サーバ経由でHBaseのポートにアクセスする必要がある
    * ⇒ SSHのPort forwardingを行うことで解決するが、下記2の問題が発生
2. HBaseはクラスタ単位で見るとポートが重複する(例: Master、RegionServerの両方共2181ポートを利用するため、localhostの2181ポートが競合する)
    * ⇒ HBaseのサーバごとにクライアントPCのローカルアドレスを分けて、Port forwardingを行う
3. HBaseクライアントでアクセスする際にプライベートDNS(ip-xx-xx-xx-xx.ap-northeast-1.compute.internal)で接続情報が返り、クライアントPCでは解決できずGet、Putが失敗する
    * ⇒ Hostsに接続情報を追加することで解決

## 作業

### HBaseのサーバごとにクライアントPCのローカルアドレスを分けて、SSH Port forwarding(課題点#1, #2を解決)
* zookeeperとHBaseのTCPポートをローカルアドレスにPort forwarding
    * HBase(Master)は2181と16000ポートをPort forwarding
    * HBase(RegionServer)は2181と16020ポートをPort forwarding

ローカルアドレス「127.0.0.3」をHBase(Master)に、ローカルアドレス「127.0.0.4」をHBase(RegionServer)に、割り当てた場合の設定

| 転送先 IP | 転送先 Port | 転送元 IP  | 転送元 Port |
| --------: | ----------: | ---------: | ----------: |
| 127.0.0.3 |       16000 | 172.16.2.3 |       16000 |
| 127.0.0.3 |        2181 | 172.16.2.3 |        2181 |
| 127.0.0.4 |       16000 | 172.16.2.4 |       16020 |
| 127.0.0.4 |        2181 | 172.16.2.4 |        2181 |

* putty設定イメージ

![](https://qiita-image-store.s3.amazonaws.com/0/102882/ed2accb8-0286-d662-d1ee-0fcbbb76cf39.png)

* 注意
    * EMRでは、HBaseのTCPポートがデフォルトと異なる
        * 参考
            * <http://docs.aws.amazon.com/ja_jp/emr/latest/ReleaseGuide/emr-hbase-configure.html>

### Hostsへの接続情報の追加(課題点#3を解決)
* Port forwarding作業時のローカルアドレスをもとにhostsにHBaseのプライベートDNSを追加

```:hosts
## HBase Master
127.0.0.3	ip-172-16-2-3.ap-northeast-1.compute.internal
## HBase RegionServer
127.0.0.4	ip-172-16-2-4.ap-northeast-1.compute.internal
```

## 確認
* [gohbase](https://github.com/tsuna/gohbase)で動作確認を行った

* 確認コード（エラー処理は割愛）

```go:main.go
package main

import (
	"fmt"
	"context"
	"github.com/tsuna/gohbase"
	"github.com/tsuna/gohbase/hrpc"
)

func main() {
    // MasterのDNSを指定
	client := gohbase.NewClient("ip-172-16-2-3.ap-northeast-1.compute.internal")
	defer client.Close()
	family := map[string][]string{"testcf": []string{"testkey"}}
	getRequest, _ := hrpc.NewGetStr(context.Background(), "testtable", "testrow", hrpc.Families(family))
	getRsp, _ := client.Get(getRequest)
	fmt.Println(string(getRsp.Cells[0].Value))
}
```

* 実行結果

```
> go run main.go
testvalue
```

## まとめ・感想
* SSH Port forwardingとHostsへのサーバ追加で、踏み台経由でもHBaseにアクセスできた
* DNSやhostnameを返すサービスであれば、同様の方法で接続ができるはず
* この方法だと接続するサーバ台数が複数台になってもPortが干渉しないのが利点
* EMRの再作成を行うとアドレスが変わり、再度作業を行う必要があるのが難点