はじめに
今回もまた書籍のまとめです。
DockerとKubernetesは普段使っていますが、体系的にちゃんと勉強したことがないなと思い、Docker/Kubernetes 実践コンテナ開発入門を読むことにしました。
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コンテナ=1プロセスを遵守すべき」という考え方が、Docker黎明期に一部のユーザー間で存在していた
- しかし1コンテナ=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リクエスト数の限界を引き上げられるため、負荷テストにも使える