GKE & Cloud Spanner 勉強会のまとめ

この記事は[GKE & Cloud Spanner 勉強会【基礎編】](https://events.withgoogle.com/gc-gke-spanner-kiso/)に参加してきたまとめです。

- 日時：2020年1月21日 17:00 - 20:00
- 場所：Google六本木オフィス＠六本木ヒルズ
- ハッシュタグ：`#gke_spanner`

## セッション 1 : GKE 入門
> 本セッションでは、Kubernetes・GKE を利用するにあたっての基礎をお話します。Kubernetes は敷居が高いと思っている方も多いと思います。実際にどのように利用するのか、どのようなコンポーネントが存在するのか、デモを交えてご紹介します。

- 資料：[GKE入門](https://www.slideshare.net/GoogleCloudPlatformJP/gke-spanner-gke)


### コンテナとKubernetes

- コンテナについて
    - Googleでは10年くらい全てのサービスをコンテナで動かしてきた。
    - 毎週40億以上のコンテナを立ち上げている。
    - 運用が楽
        - Googleではコンテナを運用することで、ワークロードが増えるのに大して人の増加よりも10倍早くコンテナが増えていった。
    - アプリとインフラを疎結合にすることが可能
    - 環境に依存せずにデプロイが可能
- なぜコンテナ？
    - 軽量、ポータブル、効率性
- コンテナのライフサイクル
    - Dockerfileの作成
    - コンテナImageの作成
    - コンテナImageをレジストリにPush
    - レジストリからdocker pull, docker runしてホストサーバーで実行
- コンテナ管理にはいくつか課題がある
    - 複数のNodeにどうやってコンテナをデプロイする？
    - Nodeがダウンしたらどうする？
    - コンテナに障害が発生したらどうする？
    - アプリケーションの更新はどうする？
    - コンテナ間の通信はどうする？
- そこでKubernetesによるCluster管理がオススメです。
- Kubernetesとは？
    - the open source cluster manager from Google
    - オープンソースのコンテナオーケストレーションシステム
    - Kubernetesとはギリシャ語で操舵手の意味
    - 略称は"k8s"
    - Go言語で書かれている
- Kubernetesが主に出来ること
    - コンテナをホストする（コンテナを動かす）
    - コンテナのスケジューリング（どこに配置するか決める）
    - （負荷が増えたら）オートスケール
    - （壊れたら）オートヒーリング
    - （新しいアプリに置き換えたい）ローリングアップデート
- 宣言型モデルになっている
    - マニフェストという設定ファイルを使う
    - 従来の命令型APIとは違い処理（How）を書くのではなく、最終的にどういう状態であって欲しいかを記述しておくとKubernetesが近づけてくれる
    - Kubernetesはマニフェストに書かれた状態を常に維持しようとするため、人の手を介さずともシステムの健常な状態を維持できる（e.g.オートヒーリング）

### Kubernetesのアーキテクチャ
- 大きくMasterとNodeに分かれている
    - Master
        - API server / Scheduler / Controller manager
    - Node
        - １つまたは複数のPodを実行するワーカーマシン（VMインスタンスや物理サーバ）
- Masterのコンポーネント
    - API Server
        - KubectlはAPI ServerをRest APIでで叩くコマンドツール
    - Scheduler
        - PodをNodeにスケジュールするコンポーネント
    - Controller
        - クラスタの状態を常に監視するバックグラウンドプロセス
        - 定義された状態と異なると、それを修正するコンポーネント
    - etcd
        - 分散KVSでクラスタの全データを格納するデータストア
- Nodeのコンポーネント
    - kubelet
        - Nodeのエージェント
        - PodのYAMLファイルに基づいて、定義されたコンテナを実行し、ストレージなどをマウントし、正常に起動していることを担保してくれる
    - kube-proxy
        - 各Nodeで実行するネットワークプロキシ
        - ServiceのIPアドレスを管理、コネクションフォワーディング
        - userspace, iptables, IPVSを使う３つのモードを選択可能


### Kubernetesにおける基本的リソース
- 基本的なリソース
    - Pod
        - Kubernetesの最小のデプロイ単位、一つ以上のコンテナが含まれている。
    - Deployment
        - 定義されたPod数と稼働中Podの差分を見て多ければ消し、少なければ立ち上げ、あるべき状態に近づける役割をする。
        - replicas:1で一つのPodが常に起動していることを保証する。
    - Service
        - Podをクラスタの内部、外部に公開するためのリソース
        - アプリケーションのエンドポイントを提供する。
            - TCP/UDPをサポート
    - Ingress
        - アプリケーションのエンドポイントを提供する。
        - L7レイヤーで負荷分散するためのリソース

### Google Kubernetes Engine (GKE) vs Kubernetes
- Demo1、クラスターを作成する
    - クラスターの名前を入力
    - ゾーンを指定
    - デフォルトプール
        - ノードをどれだけ用意するかの設定
    - 名前とゾーンの設定だけで最小構成のクラスターを2-3分くらいで作成できる。
- GKEとは？
    - Googleの提供するKubernetesのマネージドサービス
    - コマンド一発でk8sのクラスタを作成、利用開始が可能
    - マスターの管理は全てGoogleが行い、お客様はノードの使用料金のみ負担
- Masterの管理はGoogleが提供
    - MasterはGoogleによって管理されており、自動的に更新される
        - Nodeはユーザによってコントロール
        - Nodeのマイナーバージョンがマスターバージョンより３つ以上古くナルト、そのNodeは正しく動作しない場合がある。
        - 例：Masterが1.3になると1.0が実行しているNodeは動作しない場合がある
    - クラスタの設定値を持つetcdの自動バックアップ
    - GoogleのSREが全て面倒見てくれます！！
- Auto-Everything
    - k8sをスケーラブルに使うために必要なものが全て自動化されている
        - Auto-repair
            - パフォーマンスに問題があったり故障したNodesを自動的にリプレイス
        - Auto-upgrade
            - NodesのKubernetes / GKEバージョンを常に最新版に自動的に更新
        - Auto-scale(Cluster Autoscaler)
            - 需要に応じてNode pool内のNodes数を自動的に増減
        - Auto-provision
            - Cluster Autoscalerの一部として動作し、リソースに最適なNode poolを作成、削除

- KubernetesはGoogleのBorgからインスパイア
    - k8sはOSSだがGKEチームのコントリビュートは全体の４０パーセントにもなる



## セッション 2 : Cloud Spanner の技術概要
> 本セッションでは最近ホットなフルマネージドデータベース Cloud Spanner の技術概要を紹介します。 まずはなぜリレーショナルかつ整合性を担保するのに、水平方向にダウンタイムなしでスケールできるかを説明します。 その後、初めて Cloud Spanner をご利用いただくエンジニア宛によくハマる点や Tips を紹介します。 最後にデモをしながら Cloud Spanner の挙動をお見せします。 

- 資料：[Cloud Spannerの技術概要](https://www.slideshare.net/GoogleCloudPlatformJP/gke-spanner-cloud-spanner)

### Cloud Spannerの技術概要
- Spanner（NewSQL）とは？
    - リレーショナルデータベース構造
    - 水平方向スケーラビリティ
- GCPのデータベースポートフォリオ
    - NoSQL,in-memory, Relational, Object, Warehouseなどなど様々なタイプがある。
    - Spannerは一応Relationalのカテゴリに分類される。
- Cloud Spannerはthe best of RDBMS + NoSQL
    - 下表からも分かりますがCloud SpannerはRDBMSとNoSQL両方の特徴を併せ持っています。

||Cloud Spanner| Traditional RDBMS | Traditional NoSQL |
|:---|:---|:---|:---|
|Schema|⭕️**Yes**|⭕️Yes|❌No|
|Data Model|⭕️**Relational**|⭕️Relational|❌Non-relational|
|SQL|⭕️**Yes**|⭕️Yes|❌No|
|Consistency|⭕️**Strong**|⭕️Strong|❌Eventual|
|Availability|⭕️**High**|❌Failover|⭕️High|
|Scalability|⭕️**Horizontal**|❌Vertical|⭕️Horizontal|
|Replication|⭕️**Automatic**|Configurable|Configurable|

- Cloud Spannerとは？
    - Googleの良いとこ全部どりなマネージド、スケーラブル、リレーショナルデータベース、サービス
        - 完全マネージドのグローバルスケールでDBサービス
        - スキーマ、ACIDトランザクション、SQL
        - ゾーン間、リージョン間の自動synchronousレプリケーション
        - Google内部で７年以上の運用経験あり（AdWords, GooglePlay...）

### Cloud Spannerのキーコンセプト
- リージョナル＆マルチリージョン構成をとる
- シングルリージョンの場合
    - 3つのゾーンで冗長構成をとるのでゾーンが一つ壊れても問題無い
    - SLA 99.99%
- マルチリージョン構成の場合
    - 一つのリージョンがマスターになり、他のリージョンではリードオンリーになる。
    - SLA 99.999%
- シングルリージョンの場合は全てRWレプリカとして冗長構成が取られるが、マルチリージョンにナルト分散型のDBで整合性をとるために下記のようなレプリカの種類が出てくる。

|レプリカの種類|投票可能か|リーダーにできるか|読み込みを処理できるか|
|:---|:---:|:---:|:---:|
|読み書き（RW）|⭕️|⭕️|⭕️|
|読みとり専用（RO）|❌|❌|⭕️|
|ウィットネス（Witness）|⭕️|❌|❌|



- Cloud Spannerの時刻同期
    - TrueTime APIを用意して（原子時計）複数リージョン間での時刻同期をしてマルチリージョン間でのトランザクションが可能となる。
- 同期レプリケーションと強整合性
    - 一つのゾーンにアップデートすると他のゾーンにレプリケーションする。




- Splitはデータが格納される単位
- Splitとは？
    - テーブルは主キーでソートされテーブルはキーの範囲で分割される。Splitは負荷とサイズに応じて分割される。
    - Splitも負荷に応じて分割される。
- Cloud Spannerのスキーマ＆データモデル
    - プライマリキー（PK）
        - 各テーブルにPKが必須
        - PKは一つか複数
- 連番のPKはホットスポットになる
    - 新しいレコードが常にテーブルの下に入るのでSplit一つ（一つのサーバー）に負荷が集中してしまうので、PKが分散するような構成にする必要がある。

### Cloud Spannerのトランザクション
- Cloud Spannerのトランザクションと処理の方法
    - 読み書きトランザクション（RW-Txn）
        - 一つ以上の読み取りの結果に応じて書き込みをする場合、読み書きトランザクション（RW-Txn）内で読み書きを実行する必要がある。
    - 読み取り専用トランザクション（RO-Txn）
        - データの一貫したビューを取得するために、複数の読み取り呼び出しを行う場合、読み取り専用トランザクション（RO-Txn）内で読み取りを実行する必要がある。
- Cloud Spannerにおけるデータの書き込みとロック
    - 事前に読み取りせずに、書き込みを行う場合
        - ライター共有的ロックと呼ばれる共有的ロックを用いる。
        - コミットスタンプの順に順序が決定される。
    - 読み書きトランザクション
        - 読み書きトランザクションを利用する場合、データを読み取るタイミングでは共有ロックが行われる。実際に書き込みを行う際に、排他的ロックを取得し書き込みを行う。
- トランザクションを必要としない読み取り
    - Strong Read
        - 現在のタイムスタンプでの読み取りであり、この読み取り処理の開始時までにcommitされた全てのデータを確実に確認できます。Cloud Spannerのデフォルトでは、Strong Readを使用して読み取りリクエストが処理される。
    - Steal Read
        - 過去のタイムスタンプによる読み取りです。レイテンシの影響を受けやすいものの古いデータは許容できるアプリケーションの場合、Steal Readを使用するとパフォーマンスが向上することがある。