CHAPTER 01 コンテナーとKubernetes
昨今、ビジネスそのものをITによって変革させるデジタルトランスフォーメーションへの期待が高まりつつあります。その背景で、開発したアプリケーションをなるべく小さな単位で、かつ短いサイクルでデプロイしたいという開発者のニーズは、日に日に大きくなっています。しかしながら少人数の管理者で、大規模な分散環境を安定して運用管理するには、多くの克服すべき課題がたくさんあります。そこで大きく注目されているのがコンテナー技術とコンテナーオーケストレーションツールです。ここでは本書で取り上げるKubernetesとはどのようなものかを説明します。まずは、ざっくり全体像をつかみましょう。
1.1 コンテナー技術の概要
Kubernetes(クーバネティス)はオープンソースのコンテナーオーケストレーションツールです。Kubernetesを理解するうえで、背景にあるコンテナー技術がどのようなものであるかを知ることが重要です。まずは、コンテナー技術の概要について見ていきましょう。
コンテナーとは
コンテナーとは、ホストOS上に論理的な区画(コンテナー)を作り、アプリケーションを動作させるのに必要なライブラリやアプリケーションなどを1つにまとめ、あたかも個別のサーバーのように使うことができるようにしたものです。ホストOSのリソースを論理的に分離し、複数のコンテナーで共有して使います。コンテナーはサーバー仮想化に比べオーバーヘッドが少ないため、軽量で高速に動作するのが特徴です。
通常、物理サーバー上にインストールしたホストOSでは、1つのOS上で動く複数のアプリケーションは、同じシステムリソースを使います。このとき、動作する複数のアプリケーションは、データを格納するディレクトリを共有し、サーバーに設定された同じIPアドレスで通信します。そのため、複数のアプリケーションで使用しているミドルウェアやライブラリのバージョンが異なる場合などは、お互いのアプリケーションが影響を受けないよう注意が必要です。
これに対しコンテナー技術を使用すると、OSやディレクトリ、IPアドレスなどのシステムリソースを、個々のアプリケーションが占有しているように扱うことができます(図1.1)。
![図1.1 コンテナーの構成 図1.1 コンテナーの構成](http://cz-cdn.shoeisha.jp/static/images/article/11336/11336_01.jpg)
コンテナーは、アプリケーションの実行に必要なモジュールをコンテナーとしてまとめられるため、複数のコンテナーを組み合わせて1つのアプリケーションを構成するマイクロサービス型のアプリケーションと親和性が高いのが特徴です。
コンテナー技術はいくつかありますが、現在KubernetesのデフォルトになっているのがDocker(ドッカー)です。Dockerは、アプリケーションの実行に必要な環境を1つのイメージにまとめ、そのイメージを使って、さまざまな環境でアプリケーション実行環境を構築/運用するためのオープンソースソフトウェアです。
コンテナーアプリケーションの開発の流れ
具体的にアプリケーションの開発の流れを見ていきましょう。一般的なWebシステムの開発において、アプリケーションを稼働させるためには、次のものが必要です。
- アプリケーションの実行モジュール
- ミドルウェアやライブラリ群
- OS/ネットワークなどのインフラ環境設定
従来のアプリケーション開発では、図1.2のような流れで開発が進みます。そのため、開発環境やテスト環境では正しく動作していても、ステージング環境や本番環境にデプロイすると、正常に動かないこともあります。ステージング環境とは、開発したアプリケーションを本番環境にデプロイする直前に確認する環境のことです。
ここで、コンテナーを使うと、アプリケーションの実行に必要なすべてのファイル/ディレクトリ群を、まるごとコンテナーイメージとしてまとめることができます。そのため図1.3のような流れでアプリケーションを開発できます。
![図1.2 コンテナーを使わないときの開発の流れ 図1.2 コンテナーを使わないときの開発の流れ](http://cz-cdn.shoeisha.jp/static/images/article/11336/11336_02.jpg)
![図1.3 コンテナーを使ったときの一般的な開発の流れ 図1.3 コンテナーを使ったときの一般的な開発の流れ](http://cz-cdn.shoeisha.jp/static/images/article/11336/11336_03.jpg)
プログラマは開発したアプリケーションの実行に必要なすべてが含まれる、コンテナーイメージを作成します。このイメージはコンテナーのひな形になります。そして、この作成したイメージをもとにして、コンテナーを動かします。このイメージは、OSカーネルに互換性があり、コンテナーが動く環境であればどこでも動作するので(ただし、開発環境で必要なライブラリが実行環境には不要な場合もあります)、「開発/テスト環境では動くけど、本番環境では動かない」リスクを減らすことができます。
そして、アプリケーションの開発からテスト~本番環境へのデプロイが、すべてアプリケーションエンジニアの手で行うことが可能になります。そのため、デプロイのスピードを上げることができます。
- コンテナーアプリケーションのビルド(Build)
- コンテナーイメージの共有(Ship)
- コンテナーアプリケーションの実行(Run)
このコンテナーアプリケーション開発の基本となる3つのステップを具体的にDockerの場合で見ていきます。
(1)コンテナーアプリケーションのビルド(Build)
Dockerは、アプリケーションの実行に必要になるプログラム本体/ライブラリ/ミドルウェアや、OSやネットワークの設定などを1つにまとめてDockerイメージを作ります(図1.4)。Dockerでは1つのイメージには、1つのアプリケーションのみを入れておき、複数のコンテナーを組み合わせてサービスを構築するのが推奨されています。
このDockerイメージの正体は、アプリケーションの実行に必要なファイル群が格納されたディレクトリです。
![図1.4 コンテナーアプリケーションのビルド 図1.4 コンテナーアプリケーションのビルド](http://cz-cdn.shoeisha.jp/static/images/article/11336/11336_04.jpg)
(2)コンテナーイメージの共有(Ship)
コンテナーイメージはレジストリで共有できます(図1.5)。たとえば、公式のDockerレジストリであるDocker HubではUbuntuやCentOSなどのLinuxディストリビューションの基本機能を提供するベースイメージが配布されています。これらのベースイメージにミドルウェアやライブラリ、デプロイするアプリケーションなどを入れたイメージを積み重ねて独自のコンテナーイメージを作っていきます。なお、よりセキュアな環境が必要であれば、プライベートなレジストリを使うこともできます。パブリッククラウドの多くは、コンテナーイメージを共有するプライベートなレジストリサービスを提供しているので、これを利用するのがよいでしょう。
![図1.5 Dockerイメージの共有 図1.5 Dockerイメージの共有](http://cz-cdn.shoeisha.jp/static/images/article/11336/11336_05.jpg)
(3)コンテナーアプリケーションの実行(Run)
Dockerは、Linux上で、コンテナー単位でサーバー機能を動かします(図1.6)。このコンテナーのもとになるのが、Dockerイメージです。Dockerイメージさえあれば、Dockerがインストールされた環境であればどこでもコンテナーを動かすことができます。
また、Dockerイメージから複数のコンテナーを起動することもできます。コンテナーの起動/停止/破棄は、Dockerのコマンドを使います。他の仮想化技術でサーバー機能を起動するためにはOSを起動させるところから始まるため時間がかかりますが、Dockerの場合は、すでに動いているOS上でプロセスを実行するのとほぼ同じ速さで高速に起動します。
![図1.6 コンテナーアプリケーションの実行 図1.6 コンテナーアプリケーションの実行](http://cz-cdn.shoeisha.jp/static/images/article/11336/11336_06.jpg)
たとえばDockerの場合は、1つのOSを複数のコンテナーで共有しています。コンテナー内で動作するプロセスを1つのグループとして管理し、グループごとにそれぞれファイルシステムやホスト名/ネットワークなどを割り当てています。グループが異なればプロセスやファイルへのアクセスができません。
このしくみを使って、コンテナーを独立した空間として管理しています。これらを実現するため、Linuxカーネル機能(namespace、cgroupsなど)やWindowsコンテナー技術が使われています。
1.2 Kubernetesの概要
コンテナーを動かすときは、システムのトラフィックの増減や可用性要件を考慮したうえで、複数のホストマシンからなる分散環境を構築することになります。
分散環境におけるコンテナーの運用管理
コンテナーは、開発環境などのように1台のマシンで稼働させるときは手軽に導入できます。しかしながら、マルチホストで構成されたクラスター構成で稼働させるには、コンテナーの起動/停止などの操作だけでなく、ホスト間のネットワーク接続やストレージの管理、コンテナーをどのホストで稼働させるかなどのスケジューリング機能が必要になります(図1.7)。さらに、コンテナーが正常動作しているかどうかを確認するしくみも重要です。
![図1.7 分散環境でのコンテナーアプリケーションの実行 図1.7 分散環境でのコンテナーアプリケーションの実行](http://cz-cdn.shoeisha.jp/static/images/article/11336/11336_07.jpg)
これらの機能を備え、コンテナーを統合管理できるツールのことをコンテナーオーケストレーションツールと呼びます。ここでは、代表的なコンテナーオーケストレーションツールの概要を説明します。
Kubernetes
本書で取り上げるKubernetesは、コミュニティで開発が進められている、オープンソースのコンテナーオーケストレーションツールです。Cloud Native Computing Foundation(CNCF)が開発を支援しており、Google、Microsoft、Red Hat、IBMなどのエンジニアが積極的に開発に参加しています。機能も豊富で開発スピードも速く、コンテナーオーケストレーションツールのデファクトスタンダードと言っても過言ではないでしょう。
Docker(Swarmモード)
Dockerには、クラスターリング機能を提供するSwarmモードがあります。Swarmモードを使うと、複数のコンテナーをマルチホスト環境で動作させ、それらのコンテナーをまとめて1つのコマンドで操作できます。Docker1.12以前のバージョンでは、Docker Swarmという別コンポーネントが用意されていましたが、現在ではDocker本体にクラスターリング機能が組み込まれています。
Apache Mesos/Marathon
Apache Mesosは、オープンソースのクラスターオーケストレーションツールです。数百から数千のホストを持つ大規模なクラスターにも対応できるように設計されています。複数ホストのCPUやメモリ、ディスクを抽象化して、1つのリソースプールとして扱えるのが特徴です。ただし、Mesosを用いてコンテナーアプリケーションを稼働させるには、別途、コンテナー管理用のフレームワークが必要で、代表的なフレームワークとしてMarathonがあります。
Kubernetesの特徴
Kubernetes は、大規模な分散環境において少人数のエンジニアでコンテナーアプリケーションを管理することを目指したオーケストレーションツールです。
Kubernetesは、Google 社内で利用されているBorgというクラスター管理システムのアーキテクチャーをベースにして開発が始まりました。2014年6月から始まり、2015年7月にバージョン1.0となったタイミングでLinux Foundation傘下のCNCFに移管されました。
Kubernetesは、ハードウェアインフラストラクチャーを抽象化し、データセンター全体を単一の膨大な計算リソースとしてみなします。このことで、開発者は実際のサーバーを意識することなく、コンテナーアプリケーションをデプロイして実行できます。また、複数のハードウェアのコンピューティングリソースを有効に活用できます。
Kubernetesの主な機能は次のとおりです。
- 複数サーバーでのコンテナー管理
- コンテナーのデプロイ
- コンテナー間のネットワーク管理
- コンテナーの負荷分散
- コンテナーの監視
- コンテナーのアップデート
- 障害発生時の自動復旧
これらをどのようなしくみで実現しているのでしょうか?
Kubernetesを理解するうえで、欠かせないキーワードに宣言的設定とAPIセントリックがあります。
システム障害の多くは、アプリケーションをバージョンアップした、インフラの構成を変更したなど、何かしらのシステムの変化がトリガーになるものが多いでしょう。
通常のシステム開発/運用では、障害が発生するとエンジニアが状況を確認し、復旧作業を行い、サービスを正常な状態に戻します。Kubernetesでは、「システムのあるべき姿」を定義ファイルに設定し(宣言的設定)、障害が発生しても人間の手を介することなく、あるべき姿に収束させることができます。
Kubernetesの導入
コンテナーオーケストレーションツールをオンプレミス環境に導入するには、ハードウェアやネットワークの知識が必要です。クラウドの仮想マシンインスタンスで構築するときは、ハードウェアの管理からは解放されるものの、インフラ環境構築に加えてコンテナーオーケストレーションツール/監視ツールの使い方やシステム運用、障害対応など、多岐にわたるインフラ技術に関する知識が必要になります。一般的に、クラスターの構築/運用は、技術的な難易度が高く、さらにこれらを運用するにはある程度の経験を必要とします。さらに運用負荷はシステムが大規模化するにつれ増大します。
さらにもう1つ大きな問題として、このような大規模なクラスターを管理できるエンジニアが少ないということにあります。クラスターの管理には、インフラ全般の知識や運用経験だけでなく、高度なソフトウェア開発の知識も必要です。場合によってはKubernetes自体の開発に参加することも必要でしょう。このようなエンジニアを複数人常に安定して雇用しておける規模の会社でないと、安定して運用するのは現実的には難しいでしょう。
そのため、Kubernetesをまずは試してみたい、という場合はパブリッククラウドが提供するマネージドサービスを利用するのをおすすめします。ただし、コンテナーオーケストレーションのしくみやKubernetesの実装について、勉強しなくてよい、何も知らなくても簡単に利用できる、という意味ではありません。マネージドサービスの利用は、クラスターのバージョンアップやハードウェアのメンテナンス作業などにかかる作業的な負荷を軽減できるにすぎません。しくみをきちんと理解したうえで正しく利用することで、エンジニアは本業であるアプリケーション開発やコンテナーイメージの作成/実行/テスト、運用ツールの整備などに注力できます。
代表的なパブリッククラウド各社は、Kubernetesマネージドサービスを提供しています。
Amazon Elastic Container Service for Kubernetes(Amazon EKS)
Amazon Web Servicesが提供するKubernetesのマネージドサービスです。ユーザーはKubernetesのコントロールプレーンをインストール/運用保守することなく、Kubernetesクラスターを利用できます。Amazon EKSは、IAMとKubernetes RBACを連携できます。IAMエンティティにRBACロールを割り当てることで、Kubernetesマスターへのアクセス許可を制御できるのが特徴です。また、Amazon VPCでクラスターを実行するため、独自のVPCセキュリティグループおよびネットワークACLを使用できます。
Google Kubernetes Engine(GKE)
Googleが提供するKubernetesマネージドサービスです。GoogleはGmailやYouTubeなど自社で提供するサービスをコンテナーで運用しており、それらの運用ノウハウを随所に盛り込んだサービスであるというのが特徴です。クラスターの自動スケールなどの機能も備えています。GKEはGoogleによって設計および管理されているContainer-Optimized OSで実行されています。
Azure Kubernetes Service(AKS)
Microsoftが提供するAzureのコンテナーマネージドサービスです。AWSやGCPと同様にクラウド上にKubernetes のクラスターを作成/運用するサービスですが、加えてビルドツールやCI/CDパイプラインを作成するサービス、Visual StudioなどのIDEやエディターとのシームレスな統合など、より開発者向けの機能に力を入れているのが特徴です。また、MicrosoftはコンテナーデプロイサポートツールであるHelmやDraftの開発をリードしています。Kubernetesのみならず、周辺のエコシステムにも注力しているのがポイントで、幅広い業種/業態で利用しやすいでしょう。
Kubernetesのユースケース
Kubernetesの起源をたどれば、Googleが提供する自社サービスをコンテナーで運用管理するためのBorgをもとにしたオープンソースソフトウェアです。グローバルに展開するマルチメディアやゲームなど、タイムリーに新機能を提供する大規模なWeb サービスに利用されてきました。
しかし、そのプラットフォームとしての可能性はコンシューマー向けシステムだけにとどまりません。高機能で洗練されたアーキテクチャーを持つKubernetesは、オープンソースとなったことでMicrosoftやRed Hatなどエンタープライズシステムを広く扱う企業を中心にコントリビュートが進み、高い可用性やセキュリティ要件が求められる業務システムでの検討が進められています。
ここで、Kubernetesの代表的なユースケースを、Azureのシステムアーキテクチャーに沿って見てみましょう。
既存アプリケーションの移行
オンプレミス環境などで本番運用している既存アプリケーションを、コンテナーに移行して稼働させるときにKubernetesを使うケースです(図1.8)。既存アプリケーションからコンテナーイメージを作成し、コンテナーレジストリで一元管理します。Azureを使う場合、レジストリとしてAzure Container Registryが利用できます。Azure Active Directoryとの統合を通じてアクセスを制御することも可能です。また、客観的に見てコンテナー技術は永続データの管理にまだ課題を抱えています。そのため、永続データはコンテナーではなくAzure Database for MySQLなど、外部のデータストアで管理するケースが多いです。
![図1.8 既存アプリケーションの移行のパターン 図1.8 既存アプリケーションの移行のパターン](http://cz-cdn.shoeisha.jp/static/images/article/11336/11336_08.jpg)
マイクロサービスの運用管理
マイクロサービス型のアプリケーションを運用したいときにKubernetesを利用するパターンです(図1.9)。Kubernetesのもつ、水平スケーリング/自己復旧/負荷分散などの機能を活用できます。移行のケースと同じく永続データの管理はコンテナーではなくクラウドのデータ管理サービスを使うのがよいでしょう。Azureの場合、グローバル分散データベースであるAzure Cosmos DBなどを利用し拡張性を高めることができます。また、GitHubやコンテナーレジストリサービスとの連携によるCI/CDパイプラインも検討しましょう。
![図1.9 マイクロサービスの運用管理のパターン 図1.9 マイクロサービスの運用管理のパターン](http://cz-cdn.shoeisha.jp/static/images/article/11336/11336_09.jpg)
IoTデバイスのデプロイと管理
IoTの世界では、数百から場合によっては数千~数万ものIoTデバイスが必要となります。Kubernetesを使って、クラウドまたはオンプレミスで実行されるIoTデバイスに対して、必要なコンピューティングリソースをオンデマンドで提供できます(図1.10)。
加えて、IoTデバイスに対してアプリケーションの配布を行い、管理することで、作業負荷を大きく減らすことができます。
![図1.10 IoTデバイスのデプロイと管理のパターン 図1.10 IoTデバイスのデプロイと管理のパターン](http://cz-cdn.shoeisha.jp/static/images/article/11336/11336_10.jpg)
機械学習のワークロード
Kubernetes を活用する目的の1つに、コンピューティングリソースの有効活用があります。たとえば大規模なデータセットを使用する深層学習のモデルのトレーニングは、パラメーターサーバーや分散学習のためのワーカーノードの管理が必要です。コンピューティングリソースを多く必要とするワーカーノードにはGPUなど高価なハードウェアをオンデマンドで割り当てるよう制御できます(図1.11)。また、オープンソースのKubeflowなどのツールを使用して、機械学習の環境を構築できます。
![図1.11 機械学習モデルトレーニングのパターン 図1.11 機械学習モデルトレーニングのパターン](http://cz-cdn.shoeisha.jp/static/images/article/11336/11336_11.jpg)
1.3 まとめ
本章では、Kubernetesがどのような生い立ちで、何を実現するものなのかの全体像をまとめました。
- コンテナーの概要とアプリケーション開発の流れ
- 分散環境におけるコンテナーアプリケーションの運用管理
- Kubernetesの概要
Kubernetesは、今日のコンテナーの実行環境のデファクトスタンダードと言っても過言ではないでしょう。その非常に洗練されたアーキテクチャーに魅了された、世界中の多くの優秀なエンジニアたちによって機能拡張が進められている、生きたオープンソースソフトウェアです。
しかしながら、決して魔法の箱というわけではありません。Kubernetesの利用者は、そのコンセプトやしくみを学ぶことが重要です。ただし、インフラストラクチャーに関する前提知識や抽象的な概念も多く、初学者にはやや敷居の高いソフトウェアであることは否めません。
第2章以降では、実際に手を動かしながら、Kubernetesの基本的な機能を通してそのしくみをひも解いていきます。