読者です 読者をやめる 読者になる 読者になる

仕事中の問題と解決メモ。

最近はPythonとGoogle Cloud Platformがメイン。株式会社ビズオーシャンで企画と開発運用、データ活用とか。 http://mstdn.bizocean.co.jp/@uyamazak https://github.com/uyamazak/

Google Container Engine(GEK)でGCPのHTTP(S) load balancingを使うまで

Google Container Engine(以下GKE)で、サービスを作っている途中、Kubernetes(以下Kube)のService "type": "LoadBalancer"(以下LB)でいくつかの問題に当たった。

SSL証明書が面倒

KubernetesのLBにはSSL証明書を持たせられない。
そのため、Dockerコンテナに証明書を持たせる必要がある。面倒

ちなみにSSL証明書にはまだ開発中なこともあり、話題のLet's EncryptのDNS認証を使い、ローカルマシンで取得した。
prime256v1を指定して作った

Let's EncryptのDNS-01を使用して無料のSSL証明書をWebサーバなしで取得する -- ぺけみさお

・ユーザーのIPが取得できない

これが面倒ではなくどうしようもない問題だった。
KubeのLBはProxy等が一般的に出してくれる下記のようなヘッダーを返してくれない。
そのため、アプリ側でremote addressを取ると、KubeのLB等のものが出てしまい、本当のクライアントのIPは取得できなかった。

・Forwarded
・X-Forwarded-For
・X-Real-IP


※deploymentの設定でhostNetwork: trueにすると、クライアントIPが返ることもあったが、安定しなかったから没。

追記 2016/10/19

IPが取れない問題について、ドキュメントに記載があった。1.4で取れるような機能がαで追加されたもよう。でもメンテナンス時のバックエンドの切り替えや証明書などを考えるとフロントにはロードバランサー使った方が便利なので、使うことはなさそう。月2000円弱が払えないサービスなら選択肢になると思う。
Kubernetes - Creating an External Load Balancer

Loss of client source IP for external traffic

Due to the implementation of this feature, the source IP for sessions as seen in the target container will not be the original source IP of the client. This is the default behavior as of Kubernetes v1.4. However, starting in v1.4, an optional alpha feature has been added that will preserve the client Source IP for GCE/GKE environments. This feature will be phased in for other cloud providers in subsequent releases.

この二つの問題を解決するため、もっと高機能、高性能なGCEのロードバランサーを使うことにした。
こちらを使えば将来的には、リージョンを跨いだ振り分けも可能だ。



Setting Up HTTP(S) Load Balancing  |  Compute Engine Documentation  |  Google Cloud Platform

ネット上の情報だとコマンドで作ってたけど、WEB管理画面だけでも可能だった。
でも、表示が頻繁に変わるので注意が必要。

●Kubernetes側の準備

HTTP LBで公開したいdeploymentをNodeIPでexposeする

kubectl expose deployment {deployment名} --type=NodePort

#サービスの確認
kubectl describe service oceanus
Name:                   oceanus
Namespace:              default
Labels:                 run=oceanus
Selector:               run=oceanus
Type:                   NodePort
IP:                     10.3.253.176
Port:                   <unset> 80/TCP
<b>NodePort:               <unset> 30000/TCP</b>
Endpoints:              10.0.1.4:80,10.0.2.6:80
Session Affinity:       None
No events.

NodePortを控えておく。今回は30000.
もしくは覚えやすく、使ってないポートにeditで変更する

GCP管理画面側

ロードバランサー
→「ネットワーキング」
→「負荷分散」
→「ロードバランサ」を作成
→「HTTP(S)負荷分散」
→ バックエンド
 →deploymentで使っているインスタンス グループ を選択
 →ポート番号をNodePortのものに変更
 →デフォのヘルスチェックを使うか、独自に作る
→ホストとパスのルール
 →今回は全部一か所なので、指定なし
→フロントエンド
 →HTTP、80と必要な場合はHTTPSも作ってSSL証明書もアップする
→確認して完了

作成後、静的IPが付与されるので、使用するドメインDNSに登録する

console.cloud.google.com

●ファイアーウォール

HTTPロードバランサーから、kubernetesのServiceのNodePortにつながるようにする
このままでは、外部からのアクセスはできなくなっているため、HTTP LBから繋がるようにルールを追加する

同じくGCP管理画面で
→ネットワーキング
ファイアウォール ルール
→作成
 →Source IP rangesに130.211.0.0/22
  HTTP LBで共通らしい
 →ポート NodePortで指定したもの。今回は30000
 →ターゲットタグに既存のものを真似して指定

これで、HTTP LBのヘルスチェックが通るようになり、無事サービスをHTTP LB越しに公開することができた。


まだいくらかかるかわからないけど、まだ無料期間、無料分が残っているので、そちらで1か月試してみようと思う。