IBM Developer Japan Webサイトは2021年3月15日をもって終了となり、日本語コンテンツの一部は、オープンソースとして、提供予定です。 URLはこちら

Kubernetesとは何か

みなさん、こんにちは。IBMのデベロッパー・アドボケイト、Sai Vennamです。今回はKubernetesについてお話します。

ビデオをお楽しみください。

Kubernetesのアーキテクチャー:マスターとAPIサーバー

Kubernetesは、コンテナ・ベースのワークロードの実行や管理に使用できるオーケストレーション・ツールです。今回は、マネージドKubernetesサービスのリファレンス・アーキテクチャーの概要を述べ、マイクロサービスのデプロイメント方法を少し詳しく説明したいと思います。

では始めましょう。ここに描かれているのは、言ってみればパズルの両側です。左側はクラウド側で、ここには非常に重要なコンポーネント、つまりKubernetesマスターがあります。

Kubernetesマスターには重要なコンポーネントが多数含まれていますが、これから説明する最も重要な要素はAPIサーバーです。マスター上で実行されるKubernetes APIサーバーは、すべてのワークロードを実行するのに不可欠な要素で、さまざまな機能を公開しています。ユーザーはそれを使ってワークロードの動作を定義できます。

Master and API server

Kubernetesアーキテクチャー:ワーカー・ノードとkubelet

右側はお客様が管理する側で、Kubernetesベースのワーカー・ノードがあります。ここには注目していただきたい重要コンポーネントが1つあります。各Kubernetesワーカー・ノードで実行されているkubeletです。kubeletは基本的に、スケジューリングとアプリケーションの正常な動作の保証を担当し、ワーカー・ノード内で実行されます。マスターとkubeletは頻繁に連携して動作することになります。

Worker node and kubelet

スケールアウトとクラスターへのデプロイ

ここで一歩戻って考えてみましょう。Kubernetesを使おうと思うきっかけは何でしょうか? おそらく、一部のマイクロサービスがクラウド・ネイティブのアプリケーションで使われているためではないでしょうか。ご存じのとおり、マイクロサービスはネットワークを介して相互に対話しています。

説明を簡単にするため、フロントエンドとバックエンドがあり、その2つのコンポーネントをスケールアウトし、クラスターにデプロイすることにしましょう。

Yaml

Kubernetesではyamlを使用してリソースを定義します。そしてそれがAPIサーバーに送られ、最終的に実際のアプリケーションが作成されます。では、実際に始めてみましょう。まずは簡単なyamlの概略を作成して、Podをデプロイしてみます。Podはごく小さな論理単位で、これを使って簡単なコンテナをワーカー・ノード内で実行できます。

ではそれから始めます。まず、ここにあるのがPodです。一緒に必要なのがイメージで、Podに関連付けられています。これはコンテナで、事前にDocker Hubにpushしておきます。これには自分用のレジストリーを使います。

アプリケーションの名前は簡単に「f」とします。フロントエンドのfで、バージョンは1です。そしてもう1つここに追加したいものがあります。ラベルです。ラベルは非常に重要で、理由はこの後説明しますが、ラベルによって成果物の種類を正確に定義できます。ラベルには「app: f」と指定します。このアプリケーションがフロントエンドであることを示します。

Yaml

kubectlを使用した簡単なマニフェストのデプロイ

完成しました。次にこれをプロセスを通じてワーカー・ノードにpushします。 ここにあるのはkubectl、 もしかしたらKube-cuttleかもしれません、いろいろな読み方があるようですが、これを使うことで、作成したこの簡単なマニフェストをいずれかのワーカー・ノードにデプロイできるのです。

このマニフェストをkubectlを使ってpushします。Kubernetesマスター上で実行されているAPIに到達すると、APIはkubeletの1つに接続して対話します。いずれか1つのPodをデプロイするからです。そして起動します。

Using kubectl to deploy the simple manifest

こちらを見ると、APIによってアプリケーションが最初のワーカー・ノードで起動しました。先ほど指定したラベルが付いており、アプリケーションはフロントエンドです。ここで注意したいのは、これがIPアドレスも持つということです。 .1で終わる内部IPアドレスを設定するとします。この時点で、SSHでいずれかのワーカー・ノードに接続し、このIPアドレスを使ってそのアプリケーションに到達することが可能になります。

KubernetesのDeploymentとDesired State(望ましい状態)

これで簡単なアプリケーションを問題なくデプロイできます。ではさらに一歩進めましょう。KubernetesにはDeploymentと呼ばれる抽象化があります。これによって私たちは何かを行ったり、Desired State(望ましい状態)と呼ばれるものを作成したりできます。Podの必要なレプリカ数を定義して、Podに異常が起きて終了した場合に新しいPodが作成されるようにすることができます。

アプリケーションはフロントエンドであるとラベル付けされたPodがあり、そのレプリカを3つ作成するよう指定したいとします。そこで、マニフェストに戻り、Podは不要で、Podのテンプレートが必要であることをKubernetesに伝えます。これを削除して、項目を作成し、Podのテンプレートを指定します。

他にも必要なものがいくつかあります。まずレプリカの数。これは3つ必要だとしましょう。それからselectorです。このDeploymentに、この名前のデプロイ済みアプリケーションを管理するよう指定します。selectorをそれと一致させます。

前にもお話したとおり、これは完全に有効なyamlではありません。これは皆さんに、Kubernetesに必要な成果物のイメージをつかんでいただくためのものです。

最後に指定するのは、この成果物の種類です。これはDeploymentになります。

Kubernetes deployments and the desired state

KubernetesによるDesired State(望ましい状態)の管理

できました。前のPodは消去して、これが新しいマニフェストになります。これをkubectlにpushすると、それがAPIサーバーに到達します。これは一時的なオブジェクトではありません。KubernetesはDesired State(望ましい状態)を管理する必要があります。このデプロイメントが存続する限り、そして私たちが削除しない限り、継続してデプロイメントを管理します。それをここで管理します。

Deploymentを作成し、そしてレプリカは3つなので、3つを常に動作させることにします。

Kubernetes manages the desired state

Deploymentを作成したら、不具合に気付きました。これが1つしかありません。あと2つ必要です。さらにスケジューリングを行います。このアプリケーションのデプロイはリソースが存在すれば場所を問わずに行われます。

リソースは十分あり、これらのワーカー・ノードの大部分はまだ空です。そこで、各ノードに1つずつデプロイすることにします。

it decides to put one in each of the different nodes

これでDeploymentが完成しました。同じことをバックエンドについても行います。もう1つのアプリケーションのDeploymentを作成します。アプリケーションはバックエンドです。この後、それを2倍にスケールアウトしましょう。そしてここでも、アプリケーションはバックエンドです。これでうまくいきました。

So we’ll go here—application as backend

サービス間の通信

さて、今度はこれらのサービス間の通信を考えなければなりません。各PodにIPアドレスが与えられることは説明しましたが、これらのPodの一部が異常終了するケースがあることもお話しました。その場合、どこかの時点でそれらをアップデートする必要があります。Podが停止し、再開すると、新たなIPアドレスが割り当てられます。

そのため、これらのPodのいずれかに、バックエンドあるいは外部ユーザーがアクセスする場合、確実なIPアドレスが必要になります。以前はこれが問題だったのですが、サービス・レジストリーとサービス・ディスカバリー機能が生まれたおかげですっかり解決しました。Kubernetesにはこれらが組み込まれています。

次に、より安定したIPアドレスを生成するサービスを作成します。これによって複数のPodを異なるサービスとしてではなく単一のアプリケーションとしてアクセスできます。これを行うには、ここに戻って、これらの3つのPodに対するサービス定義を作成します。

Communication between services

これに伴い、マニフェストのyamlに追加が必要になります。

そのため、こちらに戻って新しいセクションをファイルに作成します。今回は「kind: service」を作成します。これに関するselectorも必要です。これも、ここで作成したラベルと一致させます。最後に必要なのは「type」です。これを公開する方法ですね。これは1秒で完了です。デフォルトではtypeはClusterIPで、これはこのサービスにクラスター内からアクセスできることを意味しています。

cluster IP

これをkubectlからデプロイし、それがマスターに到達し、こちらに接続して、これまで説明したこのような抽象化が作成されます。バックエンドについても同じものを作成しました。

deploying that through kubectl

クラスターIP

今度はクラスターIPです。省略して簡単にCl. IPとしておきましょう。これは内部IPになります。これは5で終わるものにしましょう。もう1つのサービス用に別のクラスターIPをここに設定します。こちらは.6で終わるものにします。

Cluster IP

これでIPが用意できました。これを使えばサービス間通信を確実に行えます。さらに通常はデフォルトで実行されているKubeDNSサービスですが、これによってサービス同士のアクセスがより簡単になり、名前だけでアクセスできます。「frontend」や「backend」という名前、あるいは短く「F」や「B」だけで相互にアクセスできます。

マニフェストを完成させ、サービス同士がクラスターIPを使用して対話することについても説明しました。これで、クラスター内の通信は解決しました。

ユーザーへのフロントエンドの公開

では、エンド・ユーザーにフロントエンドを公開するにはどうすればよいのでしょうか? それには、このサービスのタイプをLoadBalancerとして定義する必要があります。

Exposing the frontend to users

公開するには他の方法もあります。NodePortもその1つです。しかし、ロード・バランサーを使用することにより、ここにある実際のKubernetesワーカー・ノードの内部IPに対し、外部IPを作成できるのです。ではこれを169のアドレスにしましょう。これをエンド・ユーザーに直接公開すれば、エンド・ユーザーは直接このサービスを使ってフロントエンドにアクセスできます。

three major components

今回は3つの主要コンポーネントについて説明しました。まずPodです。PodはDeploymentによって作成され、管理されます。Deploymentによって作成されたPodへのアクセスは、Serviceを使用することで容易になります。

これらの3つの主要コンポーネントを、Kubernetesマスター、そしてすべてのワーカー・ノードと連携させることで、アプリケーションをマネージドKubernetesサービスにデプロイするためのDevOpsワークフローを根本から再定義することができます。

Sai Vennam Developer Advocate—IBM Cloud Kubernetes Service