2014年9月4日木曜日

[GCP] Compute EngineのContainer-Optimized Images


最近GCEばっかりやってます。 GCE上で良いシステム構築パターン見たいな物を見つけたいなーと思っていて、 Kubernetes、Deployment Managerと触ってきましたが、 今回のが一番しっくり来ている気がする Container−Optimized Imagesについて書きます。

Container-Optimized Imagesとは?

Container-Optimized Imagesとは名前の通りGoogle Compute Engine上でコンテナ(現状だとDocker)の扱いに 最適化されたImageで以下のようなものを最初から内包しています。
  • Debian 7
  • Docker rumtime
  • Kubernetes Kubelet

Kubelet?

KubeletはKubernetesのコンテナ起動・維持の役割を行っているコンポーネントで、 manifestファイルベースでDockerコンテナを立てることができます。 またコンテナ自体の監視・維持(ヘルスチェック)も行っておりコンテナが落ちても、 立ち上げ直してくれたりします。

Container-Optimized Imagesを使ってみる。

Container-Optimized ImagesはOpen PreviewなのでGCPを触ったことがあればすぐに利用することができます。 GCP触るのでGoogle Cloud SDKはインストールしておきます。

1. インスタンス内で立てるDockerコンテナのmanifestファイルを作成する

インスタンスを建てる前に、インスタンス内で立てるDockerコンテナのmanifestファイルを作成します。 Container-Optimized Imagesはインスタンス起動時にDockerコンテナを一緒に建てることも可能で、 せっかくなので起動と同時にDockerコンテナを建てたいと思います。
manifestファイルの仕様はここにあります。 通常のdocker runの様に、image、ports(Port Forwarding)、workingDir、、volume、command、envあたりが設定できます。
今回は単純にgoogleで公開しているgolang-helloコンテナを立ててみたいと思います。
containers.yaml
version: v1beta2
containers:
  - name: app
    image: google/golang-hello
    ports:
      - name: app-http
        hostPort: 80
        containerPort: 8080
当然複数のコンテナが必要な場合は複数指定することもできます。

2. インスタンスを起動

Cloud SDK経由でContainer−Optimized Imagesのimageを指定してインスタンスを起動します。 ※このContainer-Optimized ImagesはCloud Consoleでは表示されないため、画面から起動することはできません。
Container-Optimized ImagesはGCPのmetadataで指定されたmanifestを元にDockerコンテナをインスタンス内で起動します。 ※当然後から起動することもできます。(後述) インスタンスの起動時にmanifestをmetadataに詰めるには以下のようにします。
$ gcloud compute instances create container-optimized-instance \
  --image container-vm-v20140826 \
  --image-project google-containers \
  --zone asia-east1-a \
  --machine-type f1-micro \
  --metadata-from-file google-container-manifest=containers.yaml
なお最新のContainer−Optimized Imagesを調べたい場合は以下のコマンドを起動してください。
$ gcloud compute images list --project google-containers
最後の--metadata-from-file google-container-manifest=/path/to/manifest.yamlがコンテナのmanifestを指定している部分です。

3. 確認してみる

では実際に起動したinstanceへ入って、コンテナが起動しているか確認してみます。 ※起動後go-hello containerが起動するまで数十秒かかります。
$ gcloud compute ssh container-optimized-instance
[container-optimized-instance] $ sudo docker ps

CONTAINER ID        IMAGE                        COMMAND                CREATED             STATUS              PORTS                    NAMES
729a0956ef26        google/golang-hello:latest   "/bin/go-run"          6 seconds ago       Up 5 seconds                                 k8s--app.f546c6c--1.http--050b0083                
ca388e45c789        google/cadvisor:latest       "/usr/bin/cadvisor -"   2 minutes ago       Up 2 minutes                                 k8s--cadvisor.1207d44b--cadvisor_-_agent.file--4b947991
13eb7732a79a        kubernetes/pause:latest      "/pause"               2 minutes ago       Up 2 minutes        0.0.0.0:4194->8080/tcp   k8s--net.46426d55--cadvisor_-_agent.file--064d8229
42bbafd3efe0        kubernetes/pause:latest      "/pause"               2 minutes ago       Up 2 minutes        0.0.0.0:80->8080/tcp     k8s--net.5dc56e59--1.http--04c39388               

[container-optimized-instance] $ echo "コンテナにアクセスできるか確認"
[container-optimized-instance] $ curl http://localhost
href
="/42">Found.
起動していますね。 もちろんCompute Engineの80ポートを開けて、このインスタンスのIPアドレスにhttpアクセスすれば外部からアクセスも可能です。 Kubeletが監視をしている為、コンテナを落としてもまた起動してくれます。
[container-optimized-instance] $ sudo docker rm -f 729
729
[container-optimized-instance] $ sudo docker ps

CONTAINER ID        IMAGE                     COMMAND                CREATED             STATUS              PORTS                    NAMES
ca388e45c789        google/cadvisor:latest    "/usr/bin/cadvisor -"   6 minutes ago       Up 6 minutes                                 k8s--cadvisor.1207d44b--cadvisor_-_agent.file--4b947991
13eb7732a79a        kubernetes/pause:latest   "/pause"               7 minutes ago       Up 7 minutes        0.0.0.0:4194->8080/tcp   k8s--net.46426d55--cadvisor_-_agent.file--064d8229   
42bbafd3efe0        kubernetes/pause:latest   "/pause"               7 minutes ago       Up 7 minutes        0.0.0.0:80->8080/tcp     k8s--net.5dc56e59--1.http--04c39388                  

[container-optimized-instance] $ echo "しばらくまつ"
[container-optimized-instance] $ sudo docker ps

CONTAINER ID        IMAGE                        COMMAND                CREATED             STATUS              PORTS                    NAMES
9c0b7e8c50c6        google/golang-hello:latest   "/bin/go-run"          36 seconds ago      Up 36 seconds                                k8s--app.f546c6c--1.http--3f3e8890                
ca388e45c789        google/cadvisor:latest       "/usr/bin/cadvisor -"   7 minutes ago       Up 7 minutes                                 k8s--cadvisor.1207d44b--cadvisor_-_agent.file--4b947991
13eb7732a79a        kubernetes/pause:latest      "/pause"               7 minutes ago       Up 7 minutes        0.0.0.0:4194->8080/tcp   k8s--net.46426d55--cadvisor_-_agent.file--064d8229
42bbafd3efe0        kubernetes/pause:latest      "/pause"               7 minutes ago       Up 7 minutes        0.0.0.0:80->8080/tcp     k8s--net.5dc56e59--1.http--04c39388               
確かにgolang-helloコンテナが復活しています。

4. 後からコンテナを起動する

インスタンスを起動後にコンテナを起動する方法は2つあります。
1つ目はmetadataを更新して、インスタンスを再起動する方法です。
$ gcloud compute instances add-metadata container-optimized-instance --metadata-from-file google-container-manifest=updated-manifest.yaml
$ gcloud compute instances reset container-optimized-instance
公式のサンプルではこの方法でやっています。 ちょっと微妙ですね...
2つ目の方法は直接Kubeletにmanifestを認識させる方法です。 KubeletはKubernetesの公式ページに書いてある限りでは、以下の方法でmanifestを取り込めます。
  • HTTP Endpoints
  • etcd
  • File
  • HTTP Server
HTTP EndpointsとHTTP Serverの差はよくわからないです。 ただ現状ざっと見た感じだと、Container-Optimized Imagesの場合fileでのやり方しか出来なそうな気がしています。 ※調査不足です。
なので一旦ファイルでのやり方をやってみます。 Kubeletは20秒に1回 起動時に指定されたディレクトリを監視していてそこにmanifestが入るとそれに従ってコンテナを起動したり落としてくれます。 Container−Optimized Imagesの場合だと(デフォルト?)_etc/kubernetes/manifests/になります。
$ gcloud compute ssh container-optimized-instance
[container-optimized-instance] $ vi updated-manifest.yaml
[container-optimized-instance] $ sudo cp updated-manifest.yaml /etc/kubernetes/manifests/
これであとから起動したり、containerを変えたりできます。 もちろんkubeletをかえさず、dockerコマンドでも良いですが、多分Kubeletが監視をしてくれないです。

まとめ

Container-Optimized ImagesはMaster無しの Kubernetesという感じで、結構使いやすい感じですね。 Kubernetesでどういう恩恵がウケれるのかもイメージしやすい気がします。
Google Cloud StorageをDocker Registryとして使えるgoogle/docker-registry コンテナイメージを使って、 Private Docker Registryも一緒に立てると更に使いやすいと思います。
開発者の端末と、Container-Optimized ベースのインスタンス内に同一Cloud Storage見るようにDocker Registry立てておいて、 開発時に育てたContainerをPrivate RegistryにPushして、インスタンス側でそれを起動みたいなことをすると 相当素敵そうですね。
その辺りの建て方もその内かけたら思います。

0 件のコメント:

コメントを投稿