All Your Bugs Are Belong To Ass

Google Container Engine(GKE)が発表されたので、早速試してみた

つい先日、GoogleがGKEなるプラットフォームを発表しました。いわゆるDaaSの一種と見做して良いと思いますが、Dockerにご執心の身としては触らないわけには・・・ということで、早速試してみました。

このエントリでは、既存のdocker imageからザクッとcontainerを立ち上げ、外から見れるようにする所まで、おおまかに解説していこうと思います。

なお、今回は以前僕がdockerhubに上げたytnobody/docker-riji を使っていきます。

※基本的にGKEのGetting startedみて解かる人は、このエントリは読まなくて良さそうだと思います。

※ytnobodyは、執筆時点において、kubernetesについて全く教養を持ち合わせていません。

環境など

僕の試したクライアント環境はこんな感じです。

  • Lubuntu-14.10 amd64 on VMware

Mac? 僕は常時VMで生活してる人間なのでよくわかりませんね。多分問題なく利用できるんじゃないですか(無責任

準備

先にやっておこう

予めやっておくこととしては、以下の作業が挙げられます。

gcloud に preview コンポーネントを追加する

手始めに、gcloudにkubarnatesを操作するためのサブコマンドたちを追加するため、preview というコンポーネントを追加します。

$ gcloud component update preview

その後、gcloudに project id を食わせておきましょう。

$ gcloud config set project project-id-123

GKEクラスタを作る

次に、docker containerをまとめ上げるクラスタを作ります。your-cluster-nameのところ(=クラスタ名)は任意の名前を入れてください。

$ gcloud preview container clusters --zone=asia-east1-a create your-cluser-name

なお、この時に指定可能なzoneは、執筆時点で以下の通りです。(europe-west1-aは利用不可のようです)

  • asia-east1-a
  • asia-east1-b
  • asia-east1-c
  • europe-west1-b
  • europe-west1-c
  • us-central1-a
  • us-central1-b
  • us-central1-f

ここで指定したzoneとクラスタ名は非常に重要ですので、忘れないでください。

コマンドを実行すると、なんだかワチャワチャと情報が表示されますが、念の為以下のコマンドでクラスタのステータスを確認してみてください。

$ gcloud preview container clusters --zone=asia-east1-a list

ここまでやって、以下のような具合で出力されていれば、クラスタは無事に作成できています。

clusters:
- clusterApiVersion: 0.4.2
  containerIpv4Cidr: 10.141.0.0/16
  creationTimestamp: '2014-11-05T01:44:28+00:00'
  description: ''
  endpoint: 104.155.204.24
  masterAuth:
    password: n4Gmjl6nfjLXqFBM
    user: admin
  name: ytnobody01
  nodeConfig:
    machineType: f1-micro
    sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/backports-debian-7-wheezy-v20141021
  nodeRoutingPrefixSize: 24
  numNodes: 1
  servicesIpv4Cidr: 10.0.0.0/16
  status: running
  zone: asia-east1-a

Google Developers Consoleから見てみる

「ほんとにクラスタはできてるの?」とご心配でしたら、Google Developers Consoleにアクセスして、今回新しく作ったプロジェクトを見てみましょう。

プロジェクトメニューが左側に展開されたら、その中から 計算処理>Container Engine という順にたどってみてください。そこには以下の画像のように、先ほど作ったGKEクラスタの一覧が表示されていますね。

GKEクラスタのご様子

ではクラスタ名をクリックしてみましょう。以下の画像のようになっていることと思います。

ノードは2個ある

ここで一つ気がつく方もいるかもしれませんが、Cluster detailsのところに、インスタンスが2こ並んでますね。これについては後ほど解説します。

GKEで必須の概念

さて、このあたりで、GKEで必須となる考え方を説明します。

podとservice

GKEではpodserviceという概念が大変重要です。これらをそれぞれ雑に解説すると、、、

  • pod: docker containerの構成をまとめあげた概念。何個コンテナを用意するかとか、環境変数とか、EXPOSEするポートなんかは、全部コイツで集中管理する。

  • service: 外界とpodを接続するための設定をまとめあげた概念。手っ取り早く例えるなら、ロードバランサーです。

という感じです。ネットワーク構成的には、

               +-Master--+      +----Node----+
               |         |      |            |
Internet <---->| service |<---->| container1 |
               |         |      |            |
               +---------+      +------------+

のような具合です。上のAAはあくまで、コンテナを1個しか用意しないpodを使う場合なのですが、これがコンテナを4個とか用意する場合は、

               +-Master--+      +----Node----+
               |         |      |            |
Internet <---->| service |<---->| container1 |
               |         |      | container2 |
               +---------+      | container3 |
                                | container4 |
                                +------------+

のようになるということです。

なお実際のところ、replication controllerという重要な概念もあり、同一構成のコンテナを複数持たせたい場合に利用するようです。

MasterとNode

前述のAAを見て、もう察しの良い方は感づいたとおもいますけど、先ほどDevelopers Consoleでみた2つのノードはMasterNodeに分かれており、それぞれはっきりと役割が分担されています。

  • Master: serviceに記述された設定がそのままデプロイされる。ただし、任意のアプリケーションを動作させる等といったことはできない。
  • Node: podに記述された設定の通りにコンテナがデプロイされる。

Nodeには直接インターネットからアクセスすることはできず、必ずMasterにデプロイされたserviceを通してアクセスすることになります。

おそらく、急激に負荷が増大した際には、pod側のコンテナ数を増やしてリデプロイすることでスケールアップができる、という具合なのかと思います。(この辺、多分replication controllerを使うべきなのでしょうね)

定義すべき設定

podを定義してみる

googleのドキュメンテーションには「guestbook」のような例が有ったりするのですが、要するにpodとserviceを適切に設定すると、それっぽく見えるようになる、ということらしいです。

では、今回の例に利用するpod定義ファイルriji-master-pod.jsonをお披露目しましょう。

{
  "id": "riji-master",
  "kind": "Pod",
  "apiVersion": "v1beta1",
  "desiredState": {
    "manifest": {
      "version": "v1beta1",
      "id": "riji-master",
      "containers": [
        {
          "name": "riji-master",
          "image": "ytnobody/docker-riji",
          "ports": [
            {
              "name": "riji-server",
              "containerPort": 80,
              "destPort": 3650,
            }
          ],
          "env": [
            { 
              "name": "BLOG_REPO_URL", 
              "value": "https://github.com/ytnobody/Riji-Vanilla.git"
            }
          ]
        }
      ]
    }
  },
  "labels": { "name": "riji", "role": "master" }
}

これらの定義は、manifestを参照しながら対比してみるとよいでしょう。特徴として、manifest/containers/image に対し、dockerhubにおけるimage名を指定している点です。基本的にはdockerhubからイメージを落としてくることが前提にある様で、今回の範囲では、プライベートレジストリからのdocker pullへの取り組みについては確認できておりません。

このpodは、riji-masterというpodクラスタを構成し、コンテナを1つだけ含んでおり、80/tcpで待ち受けてるrijiを、3650/tcpに置き換えて、コンテナ外部からアクセスを受け付ける、という内容のものです。envについては、riji setup直後のデータをRiji-Vanillaという名称でgithubにpushしてあるので、それをサンプルとして利用することにしました。

serviceを定義してみる

今度はservice定義ファイルriji-master-service.jsonです。

{
  "apiVersion": "v1beta1",
  "kind": "Service",
  "id": "riji-master",
  "port": 3650,
  "containerPort": "riji-server",
  "selector": { "name": "riji", "role": "master" },
  "createExternalLoadBalancer": true
}

serviceの定義については、googleのドキュメンテーションにはそれっぽいリファレンス的なものが見当たらなかったのですが、Kubernetesのgithub project pageに若干それらしいものがあったので、参考にしつつ記述を行いました。

このserviceは、外界に対し3650/tcpを開放し、そこに来たアクセスをriji-server podクラスタに流し込む、というものです。

動かしてみる

podおよびserviceをデプロイ

以下のコマンドで、podのデプロイを行います。

$ gcloud preview container pods \
    --cluster-name=your-cluster-name \
    create riji-master-pod \
    --zone=asia-east1-a \
    --config-file=./riji-master-pod.json

実行後、以下のような方法で、podの状態確認を行いましょう。多少時間がかかるかもしれませんが、StatusがRunningになっていれば、デプロイ完了です。

$ gcloud preview container pods -n your-cluster-name list -z asia-east1-a
ID                  Image(s)               Host                           Labels                  Status
----------          ----------             ----------                     ----------              ----------
riji-master         ytnobody/docker-riji   xxx.internal/100.110.120.130   name=riji,role=master   Running

次に、serviceをデプロイします。

$ gcloud preview container services \
    --cluster-name=your-cluster-name \
    create \
    --zone=asia-east1-a \
    --config-file=./riji-master-service.json

実行後、こちらもserviceの状態確認を行いましょう。

$ gcloud preview container services -n your-cluster-name list -z asia-east1-a
ID                  Labels              Selector                Port
----------          ----------          ----------              ----------
riji-master                             name=riji,role=master   3650

このように、指定したportが表示されていればOKです。

firewall設定を調整する

「よし、アクセスしてみよう!」と思ったはいいけど、実際MasterノードのIPの3650/tcpにアクセスしてみると、timeoutします。

ちょっと調べた末にたどり着いたのは「firewallで3650/tcpへのアクセスを許可する」という作業。とはいえ、これもコマンド一発で済ませられます。

$ gcloud compute firewall-rules create riji-allow-rule --allow tcp:3650

多少時間がかかりますが、以下のような表示が出てくればOKです。

Created [https://www.googleapis.com/compute/v1/projects/your-project-123/global/firewalls/riji-allow-rule].
NAME            NETWORK SRC_RANGES RULES     SRC_TAGS TARGET_TAGS
riji-allow-rule default 0.0.0.0/0  tcp:3650

アクセスしてみる

さて、ここまで出来たら、あとはアクセスするだけ・・・なのですが、じゃあどこにアクセスすればいいんでしょう?

それを知っているのは、GCEのforwarding ruleです。以下のコマンドでアドレスを確認してみましょう。

$ gcloud compute forwarding-rules list
NAME        REGION     IP_ADDRESS     IP_PROTOCOL TARGET
riji-master asia-east1 130.211.241.18 TCP         asia-east1/targetPools/riji-master

この場合、 http://130.211.241.18:3650 へアクセスすれば良いことになります。早速アクセスしてみましょう。(なお、このアドレスはytnobodyがGKEを使って押さえているので、実際はみなさん自身のアドレスで確認してください。)

無事にrijiのサンプル記事が出てきましたでしょうか?ちゃんと見れたら、目的達成です。おめでとう。おめでとう。

実際使ってみた感想

GKEはエンタープライズ向けのDaaSという印象を受けました。実際のところ、今回構築したクラスタはレイテンシ面において大変優れているし、おそらく今回試さなかったreplication controllerを使うことで、より一層柔軟なスケーリング対応が可能となるはずです。

安定性、速度、柔軟性では、おそらくかなり優れていると思いますが、カジュアルさは一切ありませんでしたね。UX/UIの観点からみるに、正直Developers Consoleは使いやすいとは言えないですし、ドキュメンテーションもあっさりした内容で、深く掘り下げるには物足りない。

カジュアル用途、小規模用途には、すでに当ブログで紹介した tutumのほうが良さそうに思えます。しかし、大規模なコンテナクラスタを管理するとなると、GKEは良い選択肢となり得るでしょうね。

Created at
by
ytnobody
Last modified at
2014-11-06 23:44
by
ytnobody