1. 概要

Kubernetes(K8s)は、オープンソースのコンテナオーケストレーションシステムです。 これにより、コンテナー化されたアプリケーションの展開、スケーリング、および管理を自動化できます。

このチュートリアルでは、さまざまなKubernetesリソースを使用してアプリケーション(ポッド)をKubernetesにデプロイする2つの異なる方法について説明します。 以下は、Kubernetesがポッドをデプロイするために提供する2つの異なるリソースです。

まず、ステートフルアプリケーションとステートレスアプリケーションの違いを見てみましょう。

2. ステートフルおよびステートレスアプリケーション

ステートフルアプリケーションとステートレスアプリケーションの主な違いは、 ステートレスアプリケーションはデータを「保存」しません。 一方、ステートフルアプリケーションにはバッキングストレージが必要です 。 たとえば、Cassandra、MongoDB、MySQLデータベースなどのアプリケーションでは、サービスの再起動後も存続するために、ある種の永続ストレージが必要です。

ステートフルアプリケーションを実行するには、ステートを維持することが重要です。 ただし、ステートレスサービスの場合、データフローは通常一時的なものです。 また、状態はデータベースなどの別のバックエンドサービスにのみ保存されます。 関連するストレージは通常、一時的なものです。 たとえば、コンテナが再起動すると、保存されているものはすべて失われます。 組織がコンテナを採用するとき、採用が容易なため、ステートレスコンテナから始める傾向があります。

Kubernetesは、ステートレスサービスの管理でよく知られています。デプロイメントワークロードは、ステートレスアプリケーションでの作業に適しています。 展開に関する限り、ポッドは交換可能です。 StatefulSet は、管理するポッドごとに一意のIDを保持します。 それらのポッドを再スケジュールする必要があるときはいつでも同じIDを使用します。 この記事では、これについてさらに説明します。

3. 展開

3.1. 導入の理解:基本

Kubernetes Deployment は、ポッドのセットを管理するための手段を提供します。 これらは、 ReplicaSets と呼ばれる、1つ以上の実行中のコンテナーまたは重複するポッドのグループである可能性があります。 Deployment を使用すると、同じポッドのグループを共通の構成で簡単に実行できます。

まず、Kubernetes Deployment を定義してから、デプロイします。 その後、Kubernetesは、デプロイによって管理されるすべてのポッドが、設定された要件を満たしていることを確認するように機能します。 デプロイメントはポッドのスーパーバイザーです。 これにより、新しいポッドバージョンをいつどのように公開するかをきめ細かく制御できます。 また、以前のバージョンにロールバックする必要がある場合の制御も提供します。

レプリカが1のKubernetesDeployment では、コントローラーは現在の状態が ReplicaSet、の目的の状態、つまり1に等しいかどうかを確認します。 現在の状態が0の場合、 ReplicaSet。 ReplicaSetはさらにポッドを作成します。 Kubernetesを作成するとき展開名前で web-app 、それは作成します ReplicaSet 名前で web-app-このレプリカはさらに名前の付いたポッドを作成します web-app-

Kubernetes Deployment は通常、ステートレスアプリケーションに使用されます。 ただし、永続ボリュームをアタッチしてステートフルにすることで、デプロイメントの状態を保存できます。 デプロイされたポッドは同じボリュームを共有し、データはすべてのポッドで同じになります。

3.2. 展開Kubernetesのコンポーネント

以下は、Kubernetes Deploymentの主要コンポーネントです。

  • 展開テンプレート
  • PersistentVolume
  • サービス

まず、デプロイテンプレートを作成し、「deployment.yaml」として保存しましょう。 以下のテンプレートでは、永続ボリュームもアタッチしています。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app-deployment
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 1
  selector:
    matchLabels:
      app: web-app
  replicas: 3
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
        - name: web-app
          image: hello-world:nanoserver-1809
          volumeMounts:
          - name: counter
            mountPath: /app/
      volumes:
       - name: counter
         persistentVolumeClaim:
          claimName: counter

以下のテンプレートには、PersistentVolumeClaimがあります。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: counter
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 50Mi
  storageClassName: default

3.3. KubernetesでDeploymentを実行する

Deployment を実行する前に、上記のDeploymentにアクセスするためのサービスが必要です。 タイプNodePortのサービスを作成し、それを’service.yaml’として保存しましょう。

apiVersion: v1
kind: Service
metadata:
  name: web-app-service
spec:
  ports:
    - name: http
      port: 80
      nodePort: 30080
  selector:
    name: web-app
  type: NodePort

まず、以下のkubectl applyコマンドを使用してサービステンプレートを実行します。

kubectl apply -f service.yaml

次に、デプロイメントテンプレートに対して同じコマンドを実行します。

kubectl apply -f deployment.yaml

さらに、デプロイメントの詳細な説明を取得するために、kubectl describeコマンドを実行してみましょう。

kubectl describe deployment web-app-deployment

出力は次のようになります。

Name:                web-app-deployment
 Namespace:          default
 CreationTimestamp:  Tue, 30 Aug 2016 18:11:37 -0700
 Labels:             app=web-app
 Annotations:        deployment.kubernetes.io/revision=1
 Selector:           app=web-app
 Replicas:           3 desired | 3 updated | 3 total | 3 available | 0 unavailable
 StrategyType:       RollingUpdate
 MinReadySeconds:    0
 RollingUpdateStrategy:  1 max unavailable, 2 max surge
 Pod Template:
   Labels:               app=web-app
   Containers:
    web-app:
     Image:              spring-boot-docker-project:1
     Port:               80/TCP
     Environment:        <none>
     Mounts:             <none>
   Volumes:              <none>
 Conditions:
   Type          Status  Reason
   ----          ------  ------
   Available     True    MinimumReplicasAvailable
   Progressing   True    NewReplicaSetAvailable
 OldReplicaSets:   <none>
 NewReplicaSet:    web-app-deployment-1771418926 (3/3 replicas created)
 No events.

上記のセクションでは、Deploymentが内部でReplicaSetを作成することを確認します。 次に、そのReplicaSet内にポッドを内部的に作成します。 将来、現在のデプロイメントを更新すると、新しいReplicaSetが作成されます。 次に、ポッドを古いReplicaSetから新しいものに制御された速度で徐々に移動します。

更新中にエラーが発生した場合、新しいReplicaSetがReady状態になることはありません。 古いReplicaSetは再び終了せず、更新に失敗した場合に100% uptimeを保証します。 Kubernetes Deployment では、新しい機能が期待どおりに機能しない場合に備えて、以前のReplicaSetに手動でロールバックすることもできます。

4. StatefulSet s

4.1. StatefulSet を理解する:基本

Kubernetes Deploymentでは、ポッドをペットではなく牛のように扱います。 牛のメンバーの一人が病気になったり死んだりした場合は、新しい頭を購入することで簡単に交換できます。 そのような行動は目立たない。 同様に、展開中に1つのポッドがダウンすると、別のポッドが起動します。 StatefulSetsでは、ポッドに名前が付けられ、ペットのように扱われます。 ペットの1人が病気になった場合、すぐに気づきます。 StatefulSet s の場合も、ポッドと名前でやり取りするため、同じことが言えます。

StatefulSet は、その中の各ポッドに2つの安定した一意のIDを提供します。 まず、ネットワークIDを使用すると、再起動の回数に関係なく、ポッドに同じDNS名を割り当てることができます。 IPアドレスはまだ異なる可能性があるため、コンシューマーはDNS名に依存する必要があります(または変更を監視して内部キャッシュを更新します)。

次に、ストレージIDは同じままです。 ネットワークIDは、再スケジュールされたノードに関係なく、常に同じストレージインスタンスを受け取ります。

StatefulSet もコントローラーですが、Kubernetes Deployment とは異なり、 ReplicaSet を作成するのではなく、podを一意で作成します。命名規則。 各ポッドパターンに従ってDNS名を受け取ります。 たとえば、 StatefulSet 名前で mysql、 そうなる mysql-0

ステートフルセットのすべてのレプリカには独自の状態があり、各ポッドは独自のPVC(永続ボリュームクレーム)を作成します。したがって、3つのレプリカを持つStatefulSetは3つを作成します。ポッドにはそれぞれ独自のボリュームがあるため、合計3つのPVCがあります。 StatefulSet はデータを処理するため、メモリからディスクにデータを保持するために必要な時間を確保して、ポッドインスタンスを停止する際は注意が必要です。 たとえば、Kubernetesノードに障害が発生した場合など、強制削除を実行する正当な理由がまだある可能性があります。

4.2. ヘッドレスサービス

ステートフルアプリケーションには、一意のID(ホスト名)を持つポッドが必要です。 1つのポッドは、明確に定義された名前を持つ他のポッドに到達できる必要があります。 StatefulSet が機能するには、ヘッドレスサービスが必要です。 ヘッドレスサービスは、サービスIPを使用するサービスです。 したがって、関連するポッドのIPを直接返します。 これにより、プロキシではなくポッドと直接対話できます。 .spec.clusterIP。Noneを指定するのと同じくらい簡単です。

ヘッドレスサービスにはIPアドレスがありません。 内部的には、DNS名でポッドを公開するために必要なエンドポイントを作成します。 StatefulSet 定義には、ヘッドレスサービスへの参照が含まれていますが、個別に作成する必要があります。

4.3. KubernetesのStatefulSetsコンポーネント

StatefulSetの主なコンポーネントは次のとおりです。

  • StatefulSet
  • PersistentVolume
  • ヘッドレスサービス

まず、StatefulSetテンプレートを作成します。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
      volumes:
      - name: www
        persistentVolumeClaim:
          claimName: myclaim

次に、StatefulSetテンプレートに記載されているPersistentVolumeを作成します。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

最後に、上記のStatefulSetのヘッドレスサービスを作成します。

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx

4.4. KubernetesでStatefulSetを実行する

3つのコンポーネントすべてに対応するテンプレートが用意されています。 次に、 create kubectlコマンドを実行して、StatefulSetを作成しましょう。

kubectl create -f statefulset.yaml

web-0、web-1、web-2という名前の3つのポッドが作成されます。 get pods を使用して、正しい作成を確認できます。

kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
web-0     1/1       Running   0          1m
web-1     1/1       Running   0          46s
web-2     1/1       Running   0          18s

実行中のサービスを確認することもできます。

kubectl get svc nginx
NAME      TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx     ClusterIP   None         < none >      80/TCP    2m

StatefulSetReplicaSetを作成しないため、StatefulSetを以前のバージョンにロールバックすることはできません。 Statefulsetの削除またはスケールアップ/スケールダウンのみが可能です。StatefulSet を更新すると、RollingUpdateも実行されます。つまり、1つのレプリカポッドがダウンし、更新されたポッドが表示されます。上。 同様に、次のレプリカポッドも同じようにダウンします。

たとえば、上記のStatefulSetの画像を変更します。 web-2 が終了し、完全に終了すると、 web-2 が再作成され、同時にweb-1が終了します。 。 次のレプリカ、つまりweb-0でも同じことが起こります。 更新中にエラーが発生した場合は、 web-2 ダウンします、 web-1 web-0 以前の安定バージョンで実行され、引き続き稼働します。 Deployment とは異なり、StatefulSetの以前のバージョンにロールバックすることはできません。

StatefulSetを削除またはスケールダウンしても、StatefulSetに関連付けられたボリュームは削除されません。これにより、データの安全性が確保されます。これは、関連するすべてのStatefulSetリソースの自動パージよりも一般的に価値があります。 StatefulSets を削除した後、ポッドの終了は保証されません。 StatefulSet内のポッドの順序付けられた正常な終了を実現するために、削除する前にStatefulSetを0にスケールダウンすることができます。

4.5. StatefulSetの使用法

StatefulSet を使用すると、ステートフルアプリケーションとクラスター化アプリケーションをデプロイできます。 ComputeEngine永続ディスクなどの永続ストレージにデータを保存します。 これらは、Kafka、MySQL、Redis、ZooKeeper、およびその他のアプリケーション(一意で永続的なIDと安定したホスト名が必要)のデプロイに適しています。

たとえば、Solrデータベースクラスターは複数のZookeeperインスタンスによって管理されます。 このようなアプリケーションが正しく機能するためには、各Solrインスタンスがそれを制御しているZookeeperインスタンスを認識している必要があります。 同様に、Zookeeperインスタンス自体が相互に接続を確立して、マスターノードを選択します。 このような設計のため、Solrクラスターはステートフルアプリケーションの例です。 ステートフルアプリケーションの他の例には、MySQLクラスター、Redis、Kafka、MongoDBなどがあります。 このようなシナリオでは、StatefulSetが使用されます。

5. 展開対。 StatefulSet s

導入との主な違いを見てみましょう。 StatefulSet

展開 StatefulSet
デプロイメントは、ステートレスアプリケーションをデプロイするために使用されます StatefulSet は、ステートフルアプリケーションをデプロイするために使用されます
ポッドは交換可能です ポッドは交換できません。 各ポッドには永続的な識別子があり、再スケジュール時に維持されます
ポッド名は一意です ポッド名は順番に並んでいます
展開でポッドと対話するにはサービスが必要です ヘッドレスサービスは、ポッドのネットワークIDを担当します
指定されたPersistentVolumeClaimは、すべてのポッドレプリカで共有されます。 言い換えれば、共有ボリューム 各レプリカポッドがそれに関連付けられた一意のPersistentVolumeClaimを取得するように、指定されたvolumeClaimTemplates。 つまり、共有ボリュームはありません

 

Kubernetes Deployment は、アプリケーションに宣言型の更新を提供するKubernetesのリソースオブジェクトです。 デプロイメントにより、アプリケーションのライフサイクルを記述できます。 アプリに使用する画像、ポッドの数、更新方法など。

StatefulSet は、ステートフルアプリに適しています。 ステートフルアプリケーションには、一意のID(ホスト名など)を持つポッドが必要です。 ポッドは、明確に定義された名前を持つ他のポッドに到達できるようになります。 ポッドに接続するには、ヘッドレスサービスが必要です。 ヘッドレスサービスにはIPアドレスがありません。 内部的には、DNS名でポッドを公開するために必要なエンドポイントを作成します。

StatefulSet 定義には、ヘッドレスサービスへの参照が含まれていますが、個別に作成する必要があります。 StatefulSet は、ホストされているアプリケーションが再起動時にその状態とデータを保存できるように、永続的なストレージを必要とします。 StatefulSet とヘッドレスサービスが作成されると、ポッドはサービス名の前に付けられた名前で別のポッドにアクセスできます。

6. 結論

このチュートリアルでは、Kubernetesでデプロイを行う2つの方法、StatefulsetDeploymentについて説明しました。 それらの主な特性とコンポーネントを確認し、最後にそれらを比較しました。