この連載が書籍になりました!『Kubernetes完全ガイド

KubernetesのWorkloadsリソース(その1)

2018年3月28日(水)
青山 真也
連載の3回目となる今回は、ユーザーが利用できるWorkloadsリソース8種類のうち4種類を紹介する。

Deployment

Deploymentは複数のReplicaSetを管理することで、ローリングアップデートやロールバックなどを実現可能にするリソースです。

仕組みとしては単純で、

  1. 新しいReplicaSetを作成
  2. 新しいReplicaSet上のレプリカ数(Pod数)を徐々に増やす
  3. 古いReplicaSet上のレプリカ数(Pod数)を徐々に減らす
  4. (2、3をくり返す)
  5. 古いReplicaSetはレプリカ数0で保持する

というフローを取ります。

DeploymentのRolling Updateの仕組み

DeploymentのRolling Updateの仕組み

切り替えの際には

  • 新しいReplicaSet上でコンテナが起動するか・ヘルスチェックが通っているかの確認をしながら
  • ReplicaSetを移行していく際のPod数の細かい指定が可能

となっており、Kubernetesでは最も推奨されているコンテナの起動方法となっています。たとえ1コンテナだけだったとしても、Deploymentを利用して起動するのが望ましいです。

Deploymentの作成

簡単なDeploymentのサンプルを動作させてみます。まず設定ファイルですが、下記のようなファイルから、sample-deploymentを作成します。先ほど作成したReplicaSetの設定にならってDeploymentを作成します。

リスト27:サンプルのDeploymentを作成するdeployment_sample.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.12
          ports:
            - containerPort: 80

設定ファイルを元にDeploymentを作成します。「--record」を付けておくことで、アップデートを行った際の履歴を保持しておくことが可能です。

リスト28:Deploymentを作成

$ kubectl apply -f ./deployment_sample.yml --record
deployment "sample-deployment" created

履歴自体は各ReplicaSetsのmetadata.annotations.kubernetes.io/change-causeに保持されているため、下記のように確認することが可能です。また現在のReplicaSetのRevisionの番号も、同様にmetadata.annotations.deployment.kubernetes.io/revisionで確認できます。

リスト29:Deploymentの履歴を確認

$ kubectl get rs -o yaml | head
apiVersion: v1
items:
- apiVersion: extensions/v1beta1
  kind: ReplicaSet
  metadata:
    annotations:
      deployment.kubernetes.io/desired-replicas: "3"
      deployment.kubernetes.io/max-replicas: "4"
      deployment.kubernetes.io/revision: "1"
      kubernetes.io/change-cause: kubectl apply -f ./deployment_sample.yml --record

ちなみに、「kubectl run」でほぼ同等のDeploymentを生成することも可能です。デフォルトのlabelにrun: sample-deploymentが付与される点だけ違いますが、衝突の危険性も少ないため、イメージの確認など簡単な用途では、こちらを利用することも可能です。

リスト30:runコマンドでも同等の作業が行える

$ kubectl run sample-deployment --image nginx:1.12 --replicas 3 --port 80
deployment "sample-deployment" created

Deploymentを確認してみると、ほとんどReplicaSetと同じような情報が表示されます。命名規則からもDeploymentがReplicaSetを生成し、ReplicaSetがPodを作成していることが分かりやすいかと思います。

リスト31:Deploymentの結果を確認

$ kubectl get deployment
NAME                DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
sample-deployment   3         3         3            3           24s

$ kubectl get rs
NAME                           DESIRED   CURRENT   READY     AGE
sample-deployment-5cddb77dd4   3         3         3         26s

$ kubectl get pods
NAME                                 READY     STATUS    RESTARTS   AGE
sample-deployment-5cddb77dd4-npsp8   1/1       Running   0          38s
sample-deployment-5cddb77dd4-q2qjc   1/1       Running   0          38s
sample-deployment-5cddb77dd4-zwdpq   1/1       Running   0          38s

試しにDeploymentで利用しているコンテナイメージを、nginx:1.12からnginx:1.13にアップデートしてみたいと思います。イメージの更新には「kubectl set image」コマンドを利用します。

リスト32:コンテナのアップデート

$ kubectl set image deployment sample-deployment nginx-container=nginx:1.13
deployment "sample-deployment" image updated

更新後はReplicaSetが新たに作られており、そこに紐づく形でPodが再作成されます。この時、内部的にはローリングアップデートが行われているため、基本的にはサービスへの影響はありません。

リスト33:アップデート後の状態を確認

$ kubectl get deployment
NAME                DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
sample-deployment   3         3         3            3           5m

$ kubectl get rs
NAME                           DESIRED   CURRENT   READY     AGE
sample-deployment-5cddb77dd4   0         0         0         5m
sample-deployment-7575f567ff   3         3         3         1m

$ kubectl get pods
NAME                                 READY     STATUS    RESTARTS   AGE
sample-deployment-7575f567ff-9cjg9   1/1       Running   0          1m
sample-deployment-7575f567ff-pgc5g   1/1       Running   0          1m
sample-deployment-7575f567ff-tgwpl   1/1       Running   0          1m

今回紹介したDeployment、ReplicaSet、Podの関係は、下の図のようになります。また更新を行った際には、新規でReplicaSetが増えることになります。

Deployment/ReplicaSet/Podの関係

Deployment/ReplicaSet/Podの関係

Deploymentのアップデート(ReplcaSetが作成される)の条件

Deploymentでは、変更があるとReplicaSetが生成されると説明しました。この「変更」にはレプリカ数の変更などは含まれておらず、「生成されるPodの内容の変更」が必要です。より正確に言うと、spec.templateに変更があるとReplicaSetを新規で作成し、ローリングアップデートが行われます。実際にReplicaSetの定義を見てみると、spec.template以下の構造体のハッシュ値を計算し、それを利用したラベル付けで管理を行っています。また、こういった仕組みで実現されているため、再度手作業でImageなどを戻してハッシュ値が同じになった場合には、ReplicaSetを新規で作成するのではなく、既存のReplicaSetを利用するようになっています。

リスト34:Deploymentで利用されるハッシュ値

$ kubectl get rs sample-deployment-5cddb77dd4 -o yaml
…(省略)…
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
      pod-template-hash: "1788633880"
…(省略)…

今回の例では、Imageをnginx:1.12からnginx:1.13に変更したため、Pod Template Hashが再計算され、ReplicaSetが新しく作られることになりました。

PodTemplateハッシュ

PodTemplateハッシュ

変更のロールバック

Deoploymentにはロールバック機能があります。ロールバック機能の実体は、現在使用しているReplicaSetの切り替えと同義です。ReplicaSetは基本的には履歴としてレプリカ数を0にして形だけは残っているため、レプリカ数を増やすことで再度利用することが可能な状態になっています。

DeploymentのRollbackによるRelicaSetの切り替え

DeploymentのRollbackによるRelicaSetの切り替え

変更履歴を確認するには、「kubectl rollout history」コマンドを利用します。CHANGE-CAUSEの部分についてはDeployment作成時に--recordオプションを渡したため記載されていますが、--recordオプションがない場合には空になります。

リスト35:Deploymentの変更履歴の確認

$ kubectl rollout history deployment sample-deployment
deployments "sample-deployment"
REVISION  CHANGE-CAUSE
1         kubectl create --filename=deployment_sample.yml --record=true
2         kubectl set image deployment sample-deployment nginx-container=nginx:1.13

ロールバックする際には、引数でリビジョンを指定することも可能ですし、未指定の場合には一つ前のリビジョンに戻ります。

リスト36:ロールバックするリビジョンの指定

# 1つ前にロールバックする場合(デフォルトの--to-revision 0が指定される)
$ kubectl rollout undo deployment sample-deployment
deployment "sample-deployment" rolled back

# リビジョンを指定してロールバックする場合
$ kubectl rollout undo deployment sample-deployment --to-revision 1
deployment "sample-deployment" rolled back

ロールバックした際には、古いReplicaSetのほうでPodが起動される形になります。

リスト37:ロールバック後の状態を確認

$ kubectl get rs
NAME                           DESIRED   CURRENT   READY     AGE
sample-deployment-5cddb77dd4   3         3         3         5m
sample-deployment-7575f567ff   0         0         0         1m

しかしながら、実際にはこのロールバック機能を使っている利用者は少ないのではないかと思います。というのも、CI/CDのパイプラインを整備した際には、kubectl rolloutコマンドでロールバックするよりも、古いYAMLファイルを再度kubectl applyして適用したほうが相性が良いからです。この時spec.templateを同じものに戻した場合にはPod Template Hashも同じになるため、kubectl rolloutと同じように元々あったReplicaSetのほうでPodを起動します。

Deploymentのスケーリング

ReplicaSetsと同様の方法で「kubectl scale」または「kubectl apply -f」を使ってスケールさせることが可能です。

より高度なアップデート方法

今回はローリングアップデートに焦点を当てましたが、実はアップデートの種類にはrecreateという方式もあります。また、アップデートの挙動に関しては様々なパラメータが存在するため、詳細は次回以降に紹介したいと思います。

株式会社サイバーエージェント アドテク本部 Strategic Infrastructure Agency

2016年入社。OpenStackを使ったプライベートクラウドやGKE互換なコンテナプラットフォームをゼロから構築し、国内カンファレンスでのKeynoteに登壇。
その後、世界で2番目にCertified Kubernetes Application Developer、138番目にCertified Kubernetes Administratorの認定資格を取得。
現在はKubernetesやOpenStackなどOSSへのコントリビュート活動をはじめ、CNCF公式のCloud Native Meetup TokyoのOrganizerやJapan Container Daysの運営などコミュニティ活動にも従事している。

連載バックナンバー

仮想化/コンテナ技術解説
第9回

KubernetesのConfig&Storageリソース(その2)

2018/6/6
連載9回目となる今回は、Config&Storageリソースのうち、PersistentVolumeClaimについて解説する。
仮想化/コンテナ技術解説
第8回

KubernetesのConfig&Storageリソース(その1)

2018/5/31
今回と次回の2回に渡って、5種類に大別されるKubernetesのリソースのうち、Config&Storageリソースを解説する。
仮想化/コンテナ技術解説
第7回

KubernetesのDiscovery&LBリソース(その2)

2018/5/16
前回に引き続き、Discovery&LBリソースのServiceとIngressを紹介する。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています