前書き

Kubernetesは、コンテナ化されたアプリケーションを管理するためのオープンソースのコンテナオーケストレーションツールです。 https://www.digitalocean.com/community/tutorials/webinar-series-getting-started-with-kubernetes [このシリーズの前のチュートリアル]では、DigitalOceanでKubernetesを構成しました。 クラスターが稼働しているので、コンテナー化されたアプリケーションをデプロイできます。

このチュートリアルでは、Kubernetesでポッドを展開し、サービスとして公開し、レプリケーションコントローラーを介してスケーリングするときに、これらのプリミティブがどのように連携するかを学習します。

前提条件

このチュートリアルを完了するには、まずこのシリーズの前のチュートリアルhttps://www.digitalocean.com/community/tutorials/webinar-series-getting-started-with-kubernetes[Kubernetesの開始]を完了する必要があります。

ステップ1 – Kubernetesプリミティブを理解する

Kubernetesは、クライアントがアプリケーションの作成、スケーリング、終了に使用するAPIを公開します。 各操作は、Kubernetesが管理する1つ以上のオブジェクトを対象としています。 これらのオブジェクトは、Kubernetesの基本的な構成要素を形成します。 これらは、コンテナ化されたアプリケーションを管理するためのプリミティブです。

Kubernetesの主要なAPIオブジェクトの概要は次のとおりです。

  • クラスタ:コンピューティング、ストレージ、およびネットワークリソースのプール。

  • ノード:クラスター内で実行されているホストマシン。

  • 名前空間:クラスターの論理パーティション。

  • ポッド:展開の単位。

  • ラベル*および*セレクター:識別とサービス検出のためのキーと値のペア。

  • サービス:同じアプリケーションに属するポッドのコレクション。

  • レプリカセット:可用性とスケーラビリティを保証します。

  • 展開:アプリケーションのライフサイクルを管理します。

これらをさらに詳しく見てみましょう。

Kubernetesクラスターを実行する_Nodes_もオブジェクトとして扱われます。 Kubernetesの他のAPIオブジェクトと同様に管理できます。 アプリケーションの論理的な分離を可能にするために、Kubernetesは_Namespaces_の作成をサポートしています。 たとえば、組織は、開発、テスト、ステージング、および実稼働環境を実行するためにKubernetesクラスターを論理的にパーティション化できます。 各環境は、個別に管理される専用のネームスペースに配置できます。 Kubernetesは、_Master Node_を介してAPIを公開します。

KubernetesはDockerコンテナーを実行しますが、これらのコンテナーを直接展開することはできません。 代わりに、アプリケーションはKubernetesが理解できる形式でパッケージ化する必要があります。 この形式により、Kubernetesはコンテナ化されたアプリケーションを効率的に管理できます。 これらのアプリケーションには、連携する必要がある1つ以上のコンテナが含まれている場合があります。

Kubernetesでのパッケージ化と展開の基本単位は、_Pod_と呼ばれます。 各Podには、一緒に管理する必要がある1つ以上のコンテナが含まれる場合があります。 たとえば、Webサーバー(Nginx)コンテナーとキャッシュ(Re​​dis)コンテナーをポッドとして一緒にパッケージ化できます。 Kubernetesは、ポッドに属するすべてのコンテナーを論理ユニットとして扱います。 新しいPodが作成されるたびに、Pod定義で宣言されたすべてのコンテナーが作成されます。 ポッド内のすべてのコンテナーは、IPアドレス、ホスト名、ストレージなどの同じコンテキストを共有します。 リモート呼び出しやREST APIではなく、プロセス間通信(IPC)を介して互いに通信します。

コンテナをパッケージ化してKubernetesにデプロイしたら、内部および外部アクセスのためにコンテナを公開する必要があります。 データベースやキャッシュなどの特定のコンテナは、外部に公開する必要はありません。 APIとWebフロントエンドは、他の消費者とエンドユーザーによって直接アクセスされるため、一般に公開する必要があります。 Kubernetesでは、コンテナはポリシーに基づいて内部または外部に公開されます。 このメカニズムにより、データベースなどのデリケートなワークロードを公開するリスクが軽減されます。

Kubernetesのポッドは、_Services_を通じて公開されます。 各サービスは、ポートおよびプロトコル情報とともに内部または外部エンドポイントとして宣言されます。 他のポッドを含む内部コンシューマーおよびAPIクライアントなどの外部コンシューマーは、基本的な相互作用をKubernetes Servicesに依存しています。 サービスはTCPおよびUDPプロトコルをサポートします。

PodやサービスなどのKubernetesの各オブジェクトは、_Labels_および_Selectors_と呼ばれる追加のメタデータに関連付けられています。 ラベルは、Kubernetesオブジェクトに関連付けられたキーと値のペアです。 これらのラベルは、1つ以上のAPIオブジェクトを一意に識別します。 セレクターは、1つのKubernetesオブジェクトを別のオブジェクトに関連付けます。 たとえば、サービスで定義されたセレクターは、セレクターの値と一致するラベルを持つすべてのポッドをKubernetesが検索するのに役立ちます。 この関連付けにより、オブジェクトの動的検出が可能になります。 実行時に同じラベルで作成された新しいオブジェクトは即座に検出され、対応するセレクタに関連付けられます。 このサービス検出メカニズムにより、スケールインおよびスケールアウト操作などの効率的な動的構成が可能になります。

コンテナに切り替える利点の1つは、迅速なスケーリングです。 コンテナは仮想マシンと比較すると軽量であるため、数秒でスケーリングできます。 可用性が高くスケーラブルなセットアップでは、アプリケーションの複数のインスタンスをデプロイし、これらのアプリケーションのインスタンスの最小数が常に実行されていることを確認する必要があります。 コンテナ化されたアプリケーションのこの構成に対処するために、Kubernetesは、1つ以上のPodを常に実行するように設計された_Replica Sets_の概念を導入しました。 ポッドの複数のインスタンスをクラスターで実行する必要がある場合、それらはレプリカセットとしてパッケージ化されます。 Kubernetesは、レプリカセットで定義されたPodの数が常に実行モードであることを確認します。 ハードウェアまたは構成の問題によりポッドが終了した場合、Kubernetesコントロールプレーンはすぐに別のポッドを起動します。

_Deployment_オブジェクトは、ポッドとレプリカセットの組み合わせです。 このプリミティブは、KubernetesアプリケーションにPaaSのような機能をもたらします。 最小限のダウンタイムで既存の展開のローリングアップグレードを実行できます。 デプロイメントでは、カナリアデプロイメントやブルー/グリーンデプロイメントなどのパターンも使用できます。 コンテナ化されたアプリケーションのアプリケーションライフサイクル管理(ALM)の重要な部分を処理します。

ステップ2 – Kubernetesのノードと名前空間の一覧表示

DigitalOceanでKubernetesクラスターを設定の手順を実行したと仮定すると、次のコマンドを実行してすべてのノードと使用可能な名前空間:

kubectl get nodes
OutputNAME                  STATUS    ROLES     AGE       VERSION
spc3c97hei-master-1   Ready     master    10m       v1.8.7
spc3c97hei-worker-1   Ready     <none>    4m        v1.8.7
spc3c97hei-worker-2   Ready     <none>    4m        v1.8.7
kubectl get namespaces
OutputNAME                STATUS    AGE
default             Active    11m
kube-public         Active    11m
kube-system         Active    11m
stackpoint-system   Active    4m

名前空間が指定されていない場合、 `+ kubectl +`はデフォルトの名前空間を対象にします。

それでは、アプリケーションを起動しましょう。

[[step-3–-creating-and-deploying-a-pod]]
=== ステップ3 –ポッドの作成と展開

KubernetesオブジェクトはYAMLファイルで宣言され、 + kubectl + CLIを介してKubernetesに送信されます。 ポッドを定義して展開しましょう。

`+ Simple-Pod.yaml +`という新しいYAMLファイルを作成します。

nano Simple-Pod.yaml

Nginx Webサーバーに基づく1つのコンテナーでポッドを定義する次のコードを追加します。 TCPプロトコルを介してポート「80」で公開されます。 定義には、ラベル「+ name 」と「 env +」が含まれていることに注意してください。 これらのラベルを使用して、特定のポッドを識別および構成します。

Simple-Pod.yaml

apiVersion: "v1"
kind: Pod
metadata:
 name: web-pod
 labels:
   name: web
   env: dev
spec:
 containers:
   - name: myweb
     image: nginx
     ports:
       - containerPort: 80
         name: http
         protocol: TCP

次のコマンドを実行してポッドを作成します。

kubectl create -f Simple-Pod.yaml
Outputpod "web-pod" created

ポッドの作成を確認しましょう。

kubectl get pods
OutputNAME      READY     STATUS    RESTARTS   AGE
web-pod   1/1       Running   0          2m

次のステップでは、このPodをパブリックインターネットにアクセスできるようにします。

ステップ4 –サービスを介したポッドの公開

サービスは、一連のPodを内部または外部に公開します。 Nginxポッドを一般公開するサービスを定義しましょう。 NodePortを介してNginxを公開します。これは、クラスターの各ノードで開かれた任意のポートを介してPodにアクセスできるようにするスキームです。

Nginxのサービスを定義するこのコードを含む `+ Simple-Service.yaml +`という新しいファイルを作成します。

Simple-Service.yaml

apiVersion: v1
kind: Service
metadata:
 name: web-svc
 labels:
   name: web
   env: dev
spec:
 selector:
   name: web
 type: NodePort
 ports:
   - port: 80
     name: http
     targetPort: 80
     protocol: TCP

サービスは、ラベルが `+ name:web +`に一致する同じネームスペース内のすべてのポッドを検出します。 YAMLファイルのセレクターセクションは、この関連付けを明示的に定義します。

Type:NodePort宣言を介して、サービスのタイプがNodePortであることを指定します。

次に、を使用してクラスターに送信します。

kubectl create -f Simple-Service.yml

サービスが正常に作成されたことを示す次の出力が表示されます。

Outputservice "web-svc" created

ポッドが利用可能なポートを取得しましょう。

kubectl get services
OutputNAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.3.0.1     <none>        443/TCP        28m
     NodePort    10.3.0.143   <none>        80:32097/TCP   38s

この出力から、サービスがポート `+ 32097 +`で利用可能であることがわかります。 ワーカーノードの1つに接続してみましょう。

DigitalOceanコンソールを使用して、いずれかのワーカーノードのIPアドレスを取得します。

image:https://assets.digitalocean.com/articles/webinar_4_kubernetes_closer_look/kB9HmSK.png [Kubernetesクラスターに関連付けられたDigitalOceanコンソールのドロップレット。]

`+ curl `コマンドを使用して、ポート ` 31930 +`上のノードの1つにHTTPリクエストを送信します。

curl http://:32097

Nginxのデフォルトのホームページを含む応答が表示されます。

Output<!DOCTYPE html>
<html>
 <head>
   <title>Welcome to nginx!</title>
...
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
   <p><em>Thank you for using nginx.</em></p>
 </body>
</html>

ポッドとサービスを定義しました。 次に、レプリカセットを使用したスケーリングを見てみましょう。

ステップ5 –レプリカセットを介したポッドのスケーリング

レプリカセットは、クラスターで少なくとも最小数のポッドが実行されていることを確認します。 現在のポッドを削除し、レプリカセットを使用して3つのポッドを再作成しましょう。

まず、既存のポッドを削除します。

kubectl delete pod web-pod
Outputpod "web-pod" deleted

次に、新しいレプリカセット宣言を作成します。 レプリカセットの定義はポッドと同じです。 主な違いは、実行する必要があるPodの数を定義するレプリカ要素が含まれていることです。 ポッドと同様に、サービス検出に役立つメタデータとしてラベルも含まれています。

ファイル `+ Simple-RS.yml +`を作成し、このコードをファイルに追加します。

Simple-RS.yml

apiVersion: apps/v1beta2
kind: ReplicaSet
metadata:
 name: web-rs
 labels:
   name: web
   env: dev
spec:
 replicas: 3
 selector:
   matchLabels:
     name: web
 template:
   metadata:
     labels:
       name: web
       env: dev
   spec:
     containers:
     - name: myweb
       image: nginx
         ports:
           - containerPort: 80
             name: http
             protocol: TCP

ファイルを保存して閉じます。

次に、レプリカセットを作成します。

kubectl create -f Simple-RS.yml
Outputreplicaset "web-rs" created

次に、ポッドの数を確認します。

kubectl get pods
OutputNAME           READY     STATUS    RESTARTS   AGE
web-rs-htb58   1/1       Running   0          38s
web-rs-khtld   1/1       Running   0          38s
web-rs-p5lzg   1/1       Running   0          38s

NodePortを介してサービスにアクセスすると、リクエストはレプリカセットによって管理されるポッドの1つに送信されます。

ポッドの1つを削除して何が起こるかを見て、レプリカセットの機能をテストしましょう。

kubectl delete pod web-rs-p5lzg
Outputpod "web-rs-p5lzg" deleted

ポッドをもう一度見てください。

kubectl get pods
OutputNAME           READY     STATUS              RESTARTS   AGE
web-rs-htb58   1/1       Running             0          2m
web-rs-khtld   1/1       Running             0          2m

web-rs-p5lzg   1/1       Running             0          2m
web-rs-p5lzg   0/1       Terminating         0          2m

ポッドが削除されるとすぐに、Kubernetesは別のポッドを作成して、目的のカウントが維持されるようにします。

次に、展開を見てみましょう。

ステップ6 –展開に対処する

コンテナをポッドおよびレプリカセットとして展開できますが、展開を使用すると、アプリケーションのアップグレードとパッチ適用が簡単になります。 展開を使用してPodをインプレースでアップグレードできます。これはレプリカセットでは実行できません。 これにより、最小限のダウンタイムでアプリケーションの新しいバージョンを展開できます。 PaaSのような機能をアプリケーション管理にもたらします。

展開を作成する前に、既存のレプリカセットを削除します。 これにより、関連するポッドも削除されます。

kubectl delete rs web-rs
Outputreplicaset "web-rs" deleted

次に、新しい展開を定義します。 ファイル `+ Simple-Deployment.yaml +`を作成し、次のコードを追加します。

Simple-Deployment.yaml

apiVersion: apps/v1beta2
kind: Deployment
metadata:
 name: web-dep
 labels:
   name: web
   env: dev
spec:
 replicas: 3
 selector:
   matchLabels:
     name: web
 template:
   metadata:
     labels:
       name: web
   spec:
     containers:
     - name: myweb
       image: nginx
       ports:
       - containerPort: 80

展開を作成し、作成を確認します。

kubectl create -f Simple-Deployment.yml
Outputdeployment "web-dep" created

展開を表示します。

kubectl get deployments
OutputNAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
web-dep   3         3         3            3           1m

デプロイメントによりPodが作成されるため、YAMLファイルのレプリカ宣言に従って3つのPodが実行されます。

kubectl get pods
OutputNAME                       READY     STATUS    RESTARTS   AGE
web-dep-8594f5c765-5wmrb   1/1       Running   0          2m
web-dep-8594f5c765-6cbsr   1/1       Running   0          2m
web-dep-8594f5c765-sczf8   1/1       Running   0          2m

前に作成したサービスは、デプロイによって作成されたポッドにリクエストをルーティングし続けます。 これは、元のポッド定義と同じ値を含むラベルがあるためです。

展開とサービスを削除して、リソースをクリーンアップします。

kubectl delete deployment web-dep
Outputdeployment "web-dep" deleted
kubectl delete service web-svc
Outputservice "web-svc" deleted

展開の詳細については、https://kubernetes.io/docs/concepts/workloads/controllers/deployment/ [Kubernetes documentation]を参照してください。

結論

このチュートリアルでは、ポッド、サービス、レプリカセット、およびデプロイメントを使用してNginx Webサーバーをデプロイする際のKubernetesの基本的な構成要素を調査しました。

このシリーズの次のパートでは、マルチコンテナアプリケーションをパッケージ化、展開、スケーリング、および管理する方法を学習します。