Google Cloud Platform入門を読んでみた -4章編-

##経緯
Dockerの本の6章で、GCPを使った実践についての記載があった。
GCPは使ったことがなかった為、以下の本を参考に実践してみることにした。

[Google Cloud Platform 入門](https://honto.jp/ebook/pd-series_B-MBJ-20472-121415413-001-001.html)

##章立て
1章から5章にわたる章構成をした本であり、今回はKuerbenetesの知見を深める為に実施したいが故、4章のみ読むこととする。
それぞれの大まかな内容は以下の通りである。
>1章：Google Cloud Platformの概要
2章：Webアプリケーション実行基盤を構築しよう
3章：止まらないWebアプリケーション基盤を構築しよう
4章：コンテナ実行環境でマイクロサービスアーキテクチャを体験しよう
5章：機械学習を用いたGAEアプリケーション

##いざ、4章へ
初めのうちは、Dockerとは何か〜的な話から入るので、Dockerの本を既に読んでいる人は読み飛ばしてOK

###Kubernetesの基本構成
Kubernetesは複数のホストを束ねてDockerを利用する為のオーケストレーションツールで、分散環境でコンテナを稼働させる為に必要な多数の機能が提供されている。
また、Kubernetesのサーバはいくつか種類が存在する。1つずつ説明が記載されていた。
####Kubernetesのサーバ構成
#####マスターサーバ
Kubernetesクラスタ内のコンテナを操作する為のサーバ。
kubectlコマンドを用いてクラスタを構成したり、リソースを操作したりする際は、マスターサーバがコマンドからリクエストを受け取り処理を行う。
クラスタ内のノードのリソース使用状況を確認して、コンテナを起動するノードを自動的に選択する。

#####ノード(Node)
実際にDockerコンテナを動作させるサーバ。
ノードを複数用意して、クラスタを構成する。ノードの管理はマスターが行う。

#####バックエンドデータベース(etcd)
etcdと呼ばれるKVSを使って、クラスタの構成情報をまとめて管理する。

#####レジストリサーバ（Docker Registry）
クラスタ内で起動するDockerコンテナの元になるDockerイメージを管理する為のサーバ。
Docker Registryを使って、構築することが出来る。

####Kubernetesのネットワーク構成
Kubernetesはサーバを共通のネットワークに接続するだけで、Kubernetesを利用出来る。
ただし、それぞれのノードで起動するコンテナは、専用線が必要になる。
この専用線は内部ネットワークとも呼ばれ、トンネリング技術を用いて[オーバーレイ方式](https://www.publickey1.jp/blog/13/post_235.html#:~:text=%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E4%BB%AE%E6%83%B3%E5%8C%96%E3%81%AE%E6%96%B9%E5%BC%8F,%E4%B8%8A%E3%81%AB%E4%BD%9C%E3%82%8A%E5%87%BA%E3%81%99%E6%8A%80%E8%A1%93%E3%81%A7%E3%81%99%E3%80%82)で用意する。
内部ネットワークはKubernetesが提供するものではないので、別途用意が必要になる。
例として挙げられていたのは**Flannel**というツールを使うことである。
上記を使用すると、簡単に構成出来るらしい。※詳しい説明は参考資料を参照

####Kubernetesを利用したシステムへのアクセス
Kubernetesを利用するユーザーは環境へアクセスするが、それぞれ経路が存在する。
以下は、対象へのアクセス経路について記載している。
>①コンテナの起動・停止　
  　→　マスターサーバのAPIに対して指示を行う
②ノードで起動したコンテナ内のサービス　
  　→　外部ネットワークからどれか1つのノードに到達した後に、内部ネットワークを通って該当のコンテナにアクセスする


###Kubernetesによるコンテナオーケストレーション
Kubernetesを使うと、あたかも1台のコンピュータのように透過的にDockerコンテナにアクセスすることが可能となる。
システム利用者からの負荷が急増した場合でも、柔軟にスケールする仕組みや多数のコンテナを効率よく統合管理する仕組みがある。
この節では、Dockerコンテナを扱う上で理解しておくべき概念についての説明が記載されていた。
####Pod
仮想NICを共有するコンテナ群をまとめたもののこと。
Podは同一のノードにのみ配置される。
仮想NICだけでなく、Pod内のコンテナで共有するディレクトリの作成も可能。

####レプリケーションコントローラ
同一構成のPodが指定の数だけ起動している状態を作り出すもの。
例として、Webサーバが稼働するPodを負荷分散用に複数起動するような際に利用する。
Pod内のコンテナを監視する仕組みを持っており、コンテナが異常停止した場合は、該当のPodを削除して新たなPodを自動で追加起動する。
Deploymentという設定ファイルにて、レプリケーションコントローラの設定を行う。

####サービス
Podを起動しただけでは、外部からアクセスできない。そこで、起動中のPodに対して、サービスを定義することで外部からのアクセス可能なIPが用意される。
複数のPodに対して、これらをまとめた1つのサービスを定義する。
サービスに対応するIPアドレス＋ポート番号にアクセスすると、複数のPodに対する負荷分散が行われる。
サービスによって割り当てられるIPアドレスには`Cluster IP`と`External IP`の２種類がある。
以下に説明を記す。
#####Cluster IPとは
クラスタ内のPod同士で通信する為のプライベートIPのこと。

#####External IPとは
外部のクライアントから接続する為のパブリックIPのこと。

##コンテナ環境で利用する主なGCPサービスについて
###Google Container Engine
Google Container Engine(GKE)は、Dockerコンテナを管理するフルマネージドサービスのこと。
ユーザが定義したインフラ要件に基づいてコンテナをクラスタにスケジューリングして、自動的に管理する。
GKEの特徴を以下に引用する。
>・フルマネージド
　Dockerコンテナに対する高い可用性を確保して、安全に管理することが出来る。
・プライベートなコンテナレジストリの提供
　インフラの構成情報やアプリケーションの実行ファイルはインターネット上に公開できないものも多く存在する。
　Google Container Registryを使えば、Dockerイメージを保存することが可能
・スケーラブル
　アプリケーションの要求の変化に応じて、コンテナに割り当てられるクラスタリソースやコンテナクラスタのサイズを調整することが可能
・ロギング
　チェックボックス1つでロギングを有効にでき、アプリケーションがどのように動作しているのか把握することが出来る。

###Google Cloud Datastore
複数のサーバにデータを分散して保持することで、大量のデータの保存に対応した**NoSQL**データベースサービスのこと。
特徴を以下に引用する。
>・フルマネージド
　複数サーバを用いた分散環境でのデータ保持やデータセンター間でのレプリケーションは自動で行われる為、データ管理を意識する必要がない。
・使いやすい機能
　GUIを用いて、エンティティの統計やデータのバックアップ処理が実行出来る。
・さまざまなデータ型のサポート
　整数、浮動小数点数、文字列、日付、バイナリデータなど、さまざまなデータ型をサポートしている

###GCPを使ったコンテナ実行環境のアーキテクチャ
GCPのサービスを使って、コンテナ技術を活用するには、要件に応じて大きく次の3つの方法が存在するとされている。
①固有のシステム要件があるパターン
　GCEを使って、自前でインフラ環境を構築することが出来る！
②Dockerコンテナの実行環境を効率的に構築/運用したいパターン
　GKEを使って、Docker環境を構築し、コンテナオーケストレーションのインフラ構築/運用の手間を省くことが出来る！
③短期間で新規システムを開発し、運用にコストをかけたくないパターン
　Google App Engineを使って、内部的に全てのコンテナ上で動作する。
　※他の環境にアプリケーションを移行するとなった場合、移行が困難になる場合もある。

###オンラインゲームのコンテナ実行環境構築
用語説明の節が終わり、続いて実際にアプリケーションに乗せたコンテナ作りのハンズオンに入る。
まず要件定義を行うところから始まり、著書内では五目並べゲームを例に行っていた。
要件が決まり次第、GUIにて実際に設定値を決めながら構築が進んでいく。

####Docker Imageの作成
コンテナの実行環境はGUIにて作成し、続いてイメージの元となるDockerfileを作成していく。
Dockerfileはサンプルがgit上に載っているので、以下コマンドにて持ってくるのが良い。また、cloneし終わったら、対象ファイルへ移動する。

```
# git clone https://github.com/asashiho/gke-gobang-app-example
# cd gke-gobang-app-example
```

※Dockerfileは`gke-gobang-app-example/frontend/Dockerfile`の中に存在する。

上記作業にてcloneしたファイルからDockerfileを見つけ出し、そこに書き込んでいく。
ここではまず、ベースイメージの指定をすることから記載されている。
ベースイメージとは、イメージのベースとなる部分のことで、指定するには`FROM命令`と呼ばれる方法で指定する。

```bash:FROM命令
# ----- 構文 ----- #
# FROM [イメージ名]
# FROM [イメージ名]:[タグ名]
# ----- 例 ----- #
# FROM debian:8.4
```

2つ目に、Dockerfileの作成者に関する情報を記述する時は、`LABEL命令`と呼ばれる方法を使用する。

```bash:LABEL命令
# ----- 構文 ----- #
# LABEL maintainer "[Dockerfileの作成者]"
# ----- 例 ----- #
# LABEL maintainer "Your Name your_name@your_domain.com"
```

3つ目に、Dockerfileで環境変数を設定したい時は、`ENV命令`を使用する。

```bash:ENV命令
# ----- 構文 ----- #
# ENV [キー名] [値]
# ENV [キー名]=[値]
# ----- 例 ----- #
# ENV REFRESHED_AT 2017/02/28
```
上記例では、`REFRESHED_AT`に`2017/02/28`という値を設定する命令文となる。
続いて、4つ目の命令分は`FROM命令`を使用した後、指定したベースイメージに対して、「アプリケーションやミドルウェアを導入/設定」したい時は、`RUN`コマンドを使用して、コマンドを実行する。

```bash:RUN命令
# ----- 構文 ----- #
# RUN [実行したいコマンド]
# ----- 例 ----- #
# RUN apt-get -qq update;¥
      apt-get -qq -y upgrade;¥
      apt-get -qq -u install;¥
      curl python python-dev python-pip¥
      python-flask python-requests¥
```

5つ目に上がっていた命令分は`ADD命令`というもので、Dockerイメージにホスト上のファイルやディレクトリを追加する際に使用する。とあった。

```bash:ADD命令
# ----- 構文 ----- #
# ADD <ホストのファイルパス> <Dockerイメージのファイルパス>
# ADD ["<ホストのファイルパス>""<Dockerイメージのファイルパス>"]
# ----- 例 ----- #
# ADD src /opt/gobang/bin
```
上記例文では、srcディレクトリのファイルをコンテナ内の`/opt/gobang/bin`に追加する為、ADD命令を記述している。

6つ目は、`EXPOSE命令`について説明があり、これは実行中のコンテナがListenしているネットワークポートをコンテナの実行エンジンに知らせる働きを持っている。簡単に言うと、コンテナで公開するポートを指定する時は`EXPOSE命令`を用いることになる。

```bash:EXPOSE命令
# ----- 構文 ----- #
# EXPOSE <ポート番号>
# ----- 例 ----- #
# EXPOSE 8080
```
上記例文では、ゲームアプリケーションが使用する8080ポートを設定する為に命令している形となる。

7つ目に、デプロイしたアプリをコンテナで動かす為に「コンテナ内で起動しろ」という命令文を書く。
それが`CMD命令`と呼ばれるものを用いてとなる。

```bash:CMD命令
# ----- 構文 ----- #
# CMD [実行したいコマンド]
# ----- 例 ----- #
# CMD ["/opt/gobang/bin/frontend.py"]
```

####Dockerイメージの作成
いよいよ、Dockerイメージを作成していく。
作成は`docker buildコマンド`と呼ばれるものを用いて行う。
書式と例文は以下に記す。

```bash:docker_image_build
# ----- 構文 ----- #
# docker build -t [生成するイメージ名]:[タグ名] [Dockerfileのファイルパス]
# ----- 例 ----- #
# docker build -t backend:v1.0 backend-test
```

####Dockerイメージの作成有無確認
作成を実行したら、その次に本当に作成されているのか、確認する必要がある。
ここでは、確認コマンドとして`docker imagesコマンド`を用いるとある。

```bash:docker_images
# ----- 構文 ----- #
# docker images
```
上記文一つで、イメージリストが表示されるので確認が出来る。


####コンテナクラスタの削除
イメージを元に作成したコンテナクラスターの停止と削除の方法について記載されていた。

```bash:削除方法
# kubectl delete [pod名またはサービス名]
# ----- 例 ----- #
# kubectl delete service frontend-service
```

以上が4章の大まかな流れだった。
メモ程度に記載したものばかりなので、抜けている部分もある。
正しく読んでみたい方は本を購入することをおすすめする。



##参考資料
###Flannelについて
[第65回　Flannelが実現するKubernetesの仮想ネットワーク (中井悦司)](https://www.school.ctc-g.co.jp/columns/nakai/nakai65.html)

[kubernetes : kubectlコマンド一覧](https://qiita.com/suzukihi724/items/241f7241d297a2d4a55c)

[kubectlチートシート](https://kubernetes.io/ja/docs/reference/kubectl/cheatsheet/#%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AE%E5%89%8A%E9%99%A4)