「Docker/Kubernetes 実践コンテナ開発入門」まとめ

# はじめに
今回もまた書籍のまとめです。
DockerとKubernetesは普段使っていますが、体系的にちゃんと勉強したことがないなと思い、[Docker/Kubernetes 実践コンテナ開発入門](https://gihyo.jp/book/2018/978-4-297-10033-9)を読むことにしました。

# 1. Dockerの基礎
## Dockerとは
- Dockerはコンテナ型仮想化技術を実現するために実行される常駐アプリケーションと、それを操作するためのコマンドフロントインターフェースからなるプロダクト
- Dockerは開発環境の準備だけでなく、本番環境への展開やアプリケーションプラットフォームとして機能する点で優れている

## Dockerを利用する意義
- 不変な実行環境による冪等性の確保
- 実行環境構築とアプリケーション構成のコード化
- 実行環境とアプリケーションの一体化によるポータビリティ性の向上
- システムを構成するアプリケーションやミドルウェアの構成管理の容易さ

# 2. Dockerコンテナのデプロイ
## コンテナでアプリケーションを実行する
### Dockerイメージ
- Dockerコンテナを構成するファイルシステムや、実行するアプリケーションや設定をまとめたもの
- コンテナ作成のテンプレート

### Dockerコンテナ
- Dockerイメージを基に生成され、具現化されたファイルシステムとアプリケーションが実行されている状態

## Dockerイメージの操作
- Dockerの基本操作は、大きく分けて`イメージに関する操作`と`コンテナに関する操作`がある
- ここでは、`イメージに関する操作`について解説する

### docker image build
- イメージのビルド
- Dockerfileを基に、Dockerイメージを作成する

### docker search
- イメージの検索
- `Docker Hub`のレジストリに登録されているリポジトリを検索できる

### docker image pull
- イメージの取得
- DockerレジストリからDokerイメージをダウンロードしてくる

### docker image ls
- イメージの一覧
- コマンドの実行対象であるDockerホストに保持されているイメージの一覧を表示する

### docker image tag
- イメージのタグ付け
- Dockerイメージの特定のバージョンにタグ付けする

### docker image push
- イメージの公開
- 保持しているDockerイメージを、`Docker Hub`をはじめとするレジストリに登録する

## Dockerコンテナの操作
### docker container run
- Dockerイメージから、コンテナを作成・実行する

### docker container ls
- 実行中のコンテナおよび終了したコンテナの一覧を表示する

### docker container stop
- 実行中のコンテナを終了する

### docker container reatart
- コンテナの再起動
- 一度停止したコンテナは、破棄しない限りこのコマンドで再実行できる

### docker container rm
- 停止したコンテナをディスクから完全に破棄する

### docker container logs
- 実行している特定のコンテナの標準出力を表示する

### docker container exec
- 実行しているコンテナの中で任意のコマンドを実行できる

### docker container cp
- コンテナ間、コンテナ・ホスト間でファイルをコピーできる
- Dockerfileの`COPY`はイメージビルド時にホストからファイルをコピーするために利用するが、こちらは実行中のコンテナ間でのファイルのやりとりに使う

## 運用管理向けコマンド
### prune
#### docker container prune
- 実行していないコンテナを一括で削除

#### docker image prune
- 不要なイメージを削除
- コンテナと同様、イメージも蓄積するとディスクを専有するので定期的に削除が必要

#### docker system prune
- 利用されていないコンテナやイメージ、ボリューム、ネットワークといった全てのDockerリソースを一括で削除

### docker container stats
- コンテナ単位でのシステムリソースの利用状況を確認

# 3.実用的なコンテナの構築とデプロイ
## アプリケーションとコンテナの粒度
- 「**１コンテナ=1プロセス**を遵守すべき」という考え方が、Docker黎明期に一部のユーザー間で存在していた
- しかし**１コンテナ=1プロセス**の方式より、無理せず1つのコンテナで複数のプロセスを実行する方式の方がシンプルに完結するユースケースも多い
- **1コンテナに1つの関心事**
  - Dockerの公式ドキュメントでは、「コンテナは一つの関心事だけに集中すべきだ」という見解がなされている
  - 1つのコンテナは、ある1つの役割(ロール)や問題領域(ドメイン)のみにフォーカスされるべきである

## コンテナのポータビリティ
- Dockerのポータビリティ(可搬性)は大きな利点だが、完璧なものではなく、いくつかの例外が存在する
- 全てのコンテナが、あらゆるホストのDocker環境で実行されるわけではない
- アプリケーションが利用するライブラリをダイナミックリンクするケースで、課題がある

## Dockerフレンドリなアプリケーション
- コンテナの外部から挙動を制御するための手法
  - 実行時引数
  - 設定ファイル
  - アプリケーションの挙動を環境変数で制御
  - 設定ファイルに環境変数を埋め込む

## 永続化データをどう扱うか
### Data Volume
- Dockerコンテナ内のディレクトリを、ディスクに永続化するための仕組み
- ホスト・コンテナ間でのディレクトリの共有・再利用が可能になる

## コンテナ配置戦略
- 多くのリクエストを捌く必要のある実用的なシステムでは、複数のコンテナを複数のホストに配置させる必要がある

### Docker Swarm
- 複数のDockerホストを束ねてクラスタ化するためのツール
- **Docker in Docker**
  - Dockerホストとして機能するDockerコンテナを複数個立てる
  - これで、Dockerホストをコンテナで入れ子にできる

### Service
- アプリケーションを構成する複数のコンテナを制御するための概念

### Stack
- 複数の**Service**をグルーピングした単位

# 4. Swarmによる実践的なアプリケーション構築
- コンテナオーケストレーションでは、MySQL・API・WebのServiceをそれぞれ連携させて1つのアプリケーションを構築する
- このスタイルでは、Serviceに対するリクエストを複数のコンテナに分散できるため、耐久性の高いシステムを作れる
- 適切なノードのコンテナのデプロイやスケーリングをコンテナオーケストレーションの仕組みに任せられるのも、大きなメリット

# 5. Kubernetes入門
## Kubernetesとは
- コンテナの運用を自動化するためのコンテナオーケストレーションシステム
- コンテナオーケストレーションの操作のためのAPIやCLIツールも提供する
- コンテナを用いたアプリケーションのデプロイなど、様々な運用管理の自動化を実現する
- Dockerホストの管理、サーバリソースの空き具合を考慮したコンテナ配置、スケーリング、ロードバランサー、死活監視などの仕組みを備える

## Kubernetesの概念
- Kubernetesのリソースとは、アプリケーションのデプロイ構成するための部品
- コンテナとは別の粒度

## KubernetesクラスタとNode

### Kubernetesクラスタ
- リソースを管理する集合体

### Node
- Kubernetesクラスタが持つリソースで最も大きな概念
- Kubernetesクラスタの管理下に登録されているDockerホストのことで、Kubernetesでコンテナをデプロイするために利用される

## Namespace
- クラスタの中で入れ子となる仮想的なクラスタの概念
- クラスタを構築すると、予め`default`・`docker`・`kube-public`・`kube-system`というNamespaceが用意される

## Pod
- コンテナの集合体の単位

## ReplicaSet
- 同じ仕様のPodを複数生成・管理するためのリソース

## Deployment
- ReplicaSetの上位のリソース
- アプリケーションデプロイの基本単位となる

## Service
- Kubernetesクラスタ内において、Podの集合(主にReplicaSet)に対する経路やサービスディスカバリを提供するためのリソース

## Ingress
- ServiceのKubernetesクラスタの外への公開と、高度なHTTPルーティングを行う

# 6. Kubernetesのデプロイ・クラスタ構築
- クラウドへのデプロイに、GCPのマネージドKubernetesサービスであるGKE(Google Kubernetes Engine)を使う
- 自前でKubernetesクラスタを構築すると、マネージドサービスでは無いため、masterの可用性確保やKubernetesのバージョンアップといったメンテ作業を自ら行う必要がある
- 本番環境では、こういったKubernetesクラスタを適切に管理できる体制、あるいはGKEなどのマネージドサービスの利用が必要になる

# 7. Kubernetesの発展的な利用
## Kubernetesの様々なリソース
### Job
- 1つ以上のPodを作成し、正常に完了するまでを管理するリソース
- Webアプリケーションなど常駐型アプリケーションではなく、大規模な計算やバッチ指向のアプリケーション向け
- Podを複数並列で実行することで、容易にスケールアウトできる

### CronJob
- Jobは一度きりの実行だが、こちらは定期実行
- スケジューリングして定期的にPodを実行する

### Secret
- 機密情報の文字列を、Base64エンコードした状態で扱えるリソース

## ユーザー管理とRole-Based Access Control （RBAC）
### 認証ユーザー
- クラスタ外からKubernetesを操作するためのユーザーで、様々な方法で認証される

### ServiceAccount
- Kubernetes内部で管理され、Pod自身がKubernetes APIを操作するためのユーザー

### Role-Based Access Control(RBAC)
- Kubernetesのリソースへのアクセスをロールによって制御するための機能・概念
- RBACを適切に利用することで、Kubernetesリソースに対するセキュアなアクセス制御を実現できる

## Helm
- 開発環境や本番環境など、環境が複数ある場合はKubernetesクラスタも複数用意する必要がある
- この課題を解決する技術がHelm

## Kubernetesにおけるデプロイ戦略
### RollingUpdate
- Deploymentリソースのデフォルト値がRollingUpdate
- RollingUpdateは、古いバージョンのアプリケーションを実行した状態で新しいバージョンのアプリケーションを起動し、準備ができたものから順番にサービスインしていく

### BlueGreen Deployment
- デプロイ時に、既存でデプロイされているサーバ群とは別に、新しいアプリケーションがデプロイされたサーバ群を用意し、ロードバランサーやサービスディスカバリレベルで参照先を切り替えることによってデプロイする手法

# 8. コンテナの運用
## ロギングの運用
### コンテナにおけるロギング
- Dockerにはデフォルトで`logging driver`という機能があり、JSON形式でログが出力される

### コンテナログの運用
- 従来型の非コンテナのアプリケーションでは、ログローテートの機能でロギングを行う
- Dockerコンテナの場合、コンテナが停止して削除されてしまうとログも消失してしまう
- そこで、標準出力したログがホストにファイル出力される仕組みを活用する

### FluentdとElasticsearchによるログ収集・検索機構の構築
- Dockerホストを複数運用するようになると、JSONログファイルを集約して管理・閲覧する仕組みが必要になる
- そのためにログコレクタの`Fluentd`、ログを格納するデータストアとして`Elasticsearch`、データ可視化ツールの`Kibana`を使う

## Dockerホストやデーモンの運用
### コンテナのライブリストア
- Dockerデーモン(`dockerd`)は、Dockerイメージやコンテナ・ネットワークを管理するデーモン
- コンテナを実行するのに`dockerd`は欠かせないが、`dockerd`を停止してもコンテナを実行し続ける**ライブリストア**という仕組みがある

### dockerdのチューニング
#### `max-concurrent-downloads`
- `docker image pull`におけるイメージダウンロードの並列数を指定するオプション
- デフォルト値は3

#### `max-concurrent-uploads`
- `docker image push`におけるイメージアップロードの並列数を指定するオプション
- デフォルト値は5

#### `registry-mirror`
-  Docker Hubのミラーレジストリを設定するためのオプション

## 障害対策
### Docker運用での障害対策
- 障害の要因として、意図しないコンテナを起動したり誤ったイメージを上書きしたりすることが考えられる
- これを防止するために、イメージが期待した構造になっているかのテストを行う
- イメージのテストを行うフレームワークとして、`container-structure-test`がある

### Kubernetes運用での障害対策
- Kubernetesには、Nodeがダウンすると停止したPodを別のNodeに再配置してくれる`Auto-Healing`という機能がある
- しかし、システムリソースが空いているNodeを選んで配置するため、同じNodeに複数の同じPodを配置する可能性がある
- これを解決するために、**Pod AntiAffinity**という仕組みがある

# 9. より軽量なDockerイメージを作る
## 軽量なベースイメージ
### scratch
- Dockerが予約された特殊なイメージ
- 全てのDockerイメージの始祖
- 中身は空

### BusyBox
- 組み込み系システムで多く利用されるLinuxのディストリビューション
- 非常にサイズが小さいOS

### Alpine Linux
- BusyBoxをベースに作られたディストリビューション
- 「セキュリティ、シンプルさ、リソース効率を重視するパワーユーザー」向けに設計されている
- パッケージマネージャのapkが使える

## 軽量なDockerイメージをつくる
### multi-stage builds
- Docker17.05系より導入された仕組み
- ビルド成果物を生成するためのビルドコンテナと、デプロイして実行するためのコンテナに分けられる
- シームレスに軽量なDockerイメージを作れる

# 10.Dockerの様々な活用方法
- Dockerは、チーム開発で開発環境を統一・共有するのに適している
- Dockerコンテナを利用すれば、CLIツールもホストへのインストールなしで利用可能
- イメージによって、利用するCLIのバージョンを切り替えることも可能
- また、コンテナの複製、複数ノードへの展開によって発行するHTTPリクエスト数の限界を引き上げられるため、**負荷テスト**にも使える