Kubernetes, Docker Swarmって言葉よく聞くけど実はあんまりわかってない…というエンジニアに贈る。GKE概論

#はじめに

この記事は[Google Cloud Platform(1) Advent Calendar 2016](http://qiita.com/advent-calendar/2016/gcp)と[TSG Advent Calendar 2016](http://www.adventar.org/calendars/1615)として書かれています。(~~二股~~)

[GKE(Google Container Engin)](https://cloud.google.com/container-engine/)はKubernetes上に構築されたDockerコンテナのクラスタ管理やオーケストレーションを行うサービスです。

僕がGKEに興味を持ったきっかけはGoogle I/O 2016 での[デモ](https://www.youtube.com/watch?v=NEYByhiGUVQ&t=2122s)を見たことでした。

その映像を見たときは軽くドキュメントを読んだ程度だったのですが、その後メルカリに入社、ソウゾウ社に出向し、GAE/GOを本格的に使用するようになったことで、GCPの一員としてGKEを詳しく勉強する必要が出てきました。

そこで今回はGKEについて~~アドベントカレンダーでプレッシャーをかけることによって~~調べていったことをまとめる備忘録的な記事になっています。

GKEのドキュメントはあまり豊富ではないため、kubernetesの概念などの情報は主に[kubernetesのドキュメント](http://kubernetes.io/)を参照しています。そのため、GKE概論と言いながらkubernetes中心の記事になっていることをおゆるしください。

この記事がこれからGKEやkubernetesの導入を考えている方の助けになれば幸いです。

初学者なので、間違っている部分や、補足したほうがいいことなどがありましたらコメントなり編集リクエストで **優しく**　おしえていただけると嬉しいです。


## kubernetesが注目された背景

以前は、アプリケーションを展開するために、オペレーティングシステムのパッケージマネージャを使用してアプリケーションをホストにインストールしていました。しかし、この方法だと、アプリケーションの実行可能ファイル、ライブラリ、ライフサイクル、OSなどが互いに依存してしまうという難点がありました。その後ハードウェアレベルでの仮想化がすすみますが、VMも移植性がなく、重いという欠点を持っていました。そこでオペレーティングシステムレベルの仮想化に基づいたDockerなどのコンテナシステムが登場し、注目されることになりました。コンテナはVMに比べて構築が容易で、コンテナ同士は互いに独立的であるため、互いのプロセスを見ずに計算資源の使用を抑えたり、クラウド間などで移植するといったことが可能になりました。

ただ、今度はDockerの管理の問題が浮上しました。
数台レベルでコンテナを立ち上げるのはそこまで大変ではありませんが、規模が大きくなってくるとコンテナの構成、コンテナ管理、死活管理などの運用がとても大変になってしまいます。そんな悩みを解決するべく現れたのがkubernetesです。

kubernetesはアプリケーションの死活管理、オートスケール、ロードバランシング、リソース監視など、さまざまなニーズを満たす機能を備えています。また、Kubernetesは、主にマイクロサービスなどの複数のコンテナで構成されるアプリケーションを対象としていて非コンテナ化されたアプリケーションのKubernetesへの移行を容易にし、多数のクラウドプロバイダーと物理ホスト上で動作するように設計されています。さらに、KubeletのすべてのAPIが利用可能となっており、拡張開発者を推奨することでエコシステムの醸成を目指しているんだなあという姿勢を感じることができます。(個人的な感想ですが)

##kubernetesの仕組み


まず、kubernetesを説明する上でいくつか知っておくべき用語を説明していきます。

###クラスタ(Cluster)
クラスタとは、アプリケーションを実行するためにKubernetesが使用する物理マシンや仮想マシン、その他のインフラリソースのセットのことを指します。

###ノード(Node)
ノードは、Kubernetesを実行している物理マシンまたは仮想マシンで、ポッドを動かします。(スケジューリング)

###ポッド(Pod)
ポッドは複数のコンテナの集合です。Kubernetesの最小単位です。

###ラベル(Label)
ラベルは、ポッドなどのリソースにアタッチされるキー/値のペアです。ラベルを使用して、リソースのサブセットを整理し、選択することができます。

###レプリカセット(Replica Set)
元々はレプリケーションコントローラという名前でしたが、レプリカセットという名前になりました。
レプリカセットは、指定した数のポッドレプリカがいつでも実行されていることを確認します。両方とも、複製されたシステムの簡単なスケーリングを可能にし、ポッドが再起動したとき、または失敗したときにポッドの再作成を処理します。

###サービス(Service)
サービスは、単一の安定したIPアドレスや対応するDNS名など、一連のポッドとそれらにアクセスする手段を定義します。ロードバランサのようなものです。この「サービス」という命名に、マイクロサービスへの意識が感じられます。(個人的な感想です)

###シークレット(Secret)
Secretは、認証トークンなどの機密データを保管し、要求に応じてコンテナに提供することができます。イケてますね。

###ネームスペース(Namespace)
名前空間は、リソース名の接頭辞に似ています。
(マイクロサービスなどにおける)チーム間での名前の衝突を防ぐなど、さまざまなプロジェクト、チーム、または顧客がクラスタを共有する際に役立ちます。

###kubectl	
API経由でKubenetesを操作するためのクライアントツール

###アノテーション(Annotations)
識別できない補助データ（特に、ツールやシステム拡張によって操作されるデータ）を格納するために、（ラベルと比較して）大きくて人間が読めるものではないデータを保持できるキーと値のペア。アノテーション値による効率的なフィルタリングはサポートされていません。

###Deployments
DeploymentsはPodの管理をします。
Deploymentオブジェクトの目的の状態を記述するだけで、目的の状態に変更してくれます。**神ってる**。

####使ってみる

```nginx-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
```
こんな感じにyamlファイルを書いて

```
$ kubectl create -f docs/user-guide/nginx-deployment.yaml --record deployment "nginx-deployment" created 
```
これでpodを作成できます。
`--record` フラグを指定すると、作成中または更新中のリソースに現在のコマンドを記録できます。

deploymentを作成したあとは以下のように`kubectl rollout status `コマンドで簡単に状態を確認できます。

```
$ kubectl rollout status deployment/nginx-deployment deployment nginx-deployment successfully rolled out 
```

更新大変なんじゃないの？と思った方がいるかもしれません。
もし、nginx:1.7.9イメージの代わりにnginx:1.9.1イメージを使用するようにPodを更新したいな、とおもっても以下のように簡単に更新できます。

```
$ kubectl set image deployment/nginx-deployment nginx = nginx:1.9.1 deployment "nginx-deployment" image updated 
```

以下のように `--to-revision` で特定のリビジョンにロールバックしたりもできます。

```
 $ kubectl rollout undo deployment/nginx-deployment --to-revision = 2 deployment "nginx-deployment" rolled back 
```

###概念図

![k8s.png](https://qiita-image-store.s3.amazonaws.com/0/90340/9df3d2a8-331b-f729-ada1-adee667d4184.png)
[Kubernetes architecture](https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/design/architecture.md)

まず、上記は大きく、`Master components` と `Node` に分けられます。`Master components`が `Node` を管理し、GKEはこのマスターを管理してくれるサービスです。
`Node` には、アプリケーションコンテナを実行し、マスターシステムから管理するために必要なサービスがあり、Dockerを実行します。


その他の説明は以下です。

| 名前 | 説明 | 
|:-----------|:------------|
| apiserver       |        	kubernetesを操作するAPIを提供する | 
| controller-manager   |      コンテナの状態管理やノードの管理と言った各種管理作業を行う|   
| kube-proxy     |各ノードのKubernetes APIで定義されているサービスを反映し、一連のバックエンド間で簡単なTCPおよびUDPストリーム転送（ラウ​​ンドロビン）を実行する。 | 
| kubelet        |各ノード上でのコンテナ作成/削除やボリュームの割り当てなどを行う |   
 
 



##何が素晴らしいのか
僕が使ってみた感じ以下のような部分がいいかんじだなと思いました。

- アプリケーションの設定やLBまであらゆる設定が　yamlファイルでかける
- GAEと同じくstack driverで死活監視できる。[example](https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml)もしっかりあるので[prometheus](https://github.com/prometheus)使っても良さそう。
- ログはCloud Loggingでみれる



##もっと知りたい
kubernetesについてもっと詳しく知りたいなという方は[multi-cluster doc](https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/admin/multi-cluster.md)や[cluster federation proposal](https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/proposals/federation.md)も参考にしてみてください。