LoginSignup
4
1

More than 3 years have passed since last update.

【KubernetesでPodをスケーリングさせる】その1- 手動スケーリング

Last updated at Posted at 2019-06-12

概要

KubernetesでPodを手動でスケールアウトさせる方法。
replicas: 2で作成したpodを4つにスケールアウトさせてみる。
ここではMinikube環境を利用したが、その他の環境の場合は適宜読み替えてください。

オートスケーリングさせる方法はこちら。
【KubernetesでPodをスケーリングさせる】その2 - オートスケーリング

Nodeをスケーリングさせることもできるが、ここでは触れない。
参考:Kuberentes クラスタのオートスケール

目次

環境

  • CentOS 7.6
  • Minikube v1.1.1
  • Kubernetes v1.14.3

関連記事

Deploymentの仕組み

スケーリングをするためには、Deploymentの仕組みについての理解が必要となる。

  • DeploymentはReplicaSetを生成、管理し、ReplicaSetはPodの生成、管理をする。
  • コンテナイメージの変更などのアップデートがあった際には、新規にReplicaSetを生成し、旧ReplicaSetから新ReplicaSetへPodが置き換えられていく。(ローリングアップデート)
    • 旧ReplicaSetも一定期間保持され、ロールバックが可能となる。
  • Replica数の変更のときは、新たなReplicaSetは生成せずに既存のReplicaSetの下のPod数を変更する。

参考: Deployment の仕組み

事前準備

Dockerコンテナにmountするディレクトリとファイルを作成

コンテナのホスト名を返すスクリプトを実装。
スケールアウト実施後に、ロードバランシングされていることを確認するために、アクセスするたびに異なるコンテナにアクセスが行っていることを確認するため、ホスト名を取得するプログラムを仕込む。

後述のDeploymentの設定で、Dockerコンテナのvolumeとして/home/username/containers/web/html/をmountするので、その配下にindex.phpを設置する。

/home/username/containers/web/html/index.php
<?php echo gethostname() . "\n"; ?>

Deploymentを定義

deployment.yml
kind: Deployment
apiVersion: apps/v1
metadata:
  name: http-deployment
spec:
  selector:
    matchLabels:
      ########################################################
      # deploymentの.spec.selector.matchLabels.appの値と、
      # 後述のservice.ymlの.spec.selector.appの値を合わせることで、
      # serviceからdeploymentにリクエストを流すことが可能となる。
      ########################################################
      app: http-app
  # podの設定
  replicas: 2
  # ここでは触れないが、このPodTemlateの部分に変更があったときに、ローリングアップデートが実行される
  template:
    metadata:
      labels:
        # 上記のspec.selector.matchLabels.appと合っていないとエラーとなる
        app: http-app
    spec:
      containers:
        # Dockerコンテナ名
        - name: http-container
          # 利用するDockerイメージ
          image: php:7.0-apache
          # localイメージ利用。ただし、localに指定したイメージが存在しない場合はレポジトリを参照する
          imagePullPolicy: IfNotPresent
          ports:
            # service.ymlで定義する外部公開用port設定の箇所と名前を合わせることでbindされる
            # nameは15文字以内でないとエラーになる
            - name: ha-inner-port
              # コンテナ内のport
              containerPort: 80
          # mountするディレクトリ:コンテナ側の設定
          volumeMounts:
            - name: documentroot
              mountPath: /var/www/html
      # mountするディレクトリ:ホストOS側の設定
      volumes:
        - name: documentroot
          hostPath:
            path: /home/username/containers/web/html

Serviceを定義

service.yml
kind: Service
apiVersion: v1
metadata:
  # service名
  name: http-service
spec:
  selector:
    ########################################################
    # 前述のdeploymentの.spec.selector.matchLabels.appの値と、
    # service.ymlの.spec.selector.appの値を合わせることで、
    # serviceからdeploymentにリクエストを流すことが可能となる。
    ########################################################
    app: http-app
  ports:
    - name: ha-outer-port
      # 外部公開するport
      port: 8080
      # deployment.ymlで定義したport名と合わせることでbindされる
      targetPort: ha-inner-port
    # 以下のようにtargetPortを名前で合わせずに明記してもOK
    #- name: ha-outer-port
    #  protocol: "TCP"
    #  port: 8080
    #  targetPort: 80
  type: NodePort

作成

$ sudo kubectl create -f deployment.yml -f service.yml
deployment.extensions/http-deployment created
service/http-service created

pod, service, deploymentの内容を確認

service/http-service、deployment.apps/http-deployment、それぞれのSELECTORがapp=http-appになっていることを確認。labelが一致していることで、ServiceからDeploymentへのリクエストが可能となる。

$ sudo kubectl get all
NAME                                   READY   STATUS    RESTARTS   AGE
pod/http-deployment-7fc8f549fd-4nwxr   1/1     Running   0          1s
pod/http-deployment-7fc8f549fd-gkjxl   1/1     Running   0          1s

NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/http-service   NodePort    10.100.109.122   <none>        8080:32021/TCP   2s
service/kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP          26h

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/http-deployment   2/2     2            2           2s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/http-deployment-7fc8f549fd   2         2         2       2s

serviceの確認

service/http-serviceをdescribeして、以下を確認する。

  • Selectorが設定したラベルになっている
  • Port、TargetPortが設定したとおりになっている
  • replica数を2にしたので、Endpointsが2つある
$ sudo kubectl describe service/http-service
Name:                     http-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=http-app
Type:                     NodePort
IP:                       10.100.109.122
Port:                     ha-outer-port  8080/TCP
TargetPort:               ha-inner-port/TCP
NodePort:                 ha-outer-port  32021/TCP
Endpoints:                192.168.249.5:80,192.168.249.6:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

ロードバランシングされていることを確認

コンテナのホスト名を返すindex.phpを実装したので、curlで何度かアクセスしてみる。
そうすると、replicationされているので、実行するたびに違うホスト名が返ってくる。
これで、ロード・バランシングされていることを確認できる。

$ curl $(sudo minikube service http-service --url)
http-deployment-7fc8f549fd-gkjxl
$ curl $(sudo minikube service http-service --url)
http-deployment-7fc8f549fd-4nwxr

podを削除してみる

削除する前に、podがreplicaで設定したとおり2つ存在していることを確認する。

$ sudo kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE
http-deployment-7fc8f549fd-4nwxr   1/1     Running   0          68m
http-deployment-7fc8f549fd-gkjxl   1/1     Running   0          68m

podを1つ削除する。

$ sudo kubectl delete pod http-deployment-7fc8f549fd-4nwxr
pod "http-deployment-7fc8f549fd-4nwxr" deleted

削除後、podを確認すると新しく生成され、replicaで指定したとおり、常に2つに保たれていることが分かる。

$ sudo kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE
http-deployment-7fc8f549fd-gkjxl   1/1     Running   0          69m
http-deployment-7fc8f549fd-xtjlr   1/1     Running   0          12s

参考

スケールアウト実行

replicaの数を4つにする

$ sudo kubectl scale deployments/http-deployment --replicas=4
deployment.extensions/http-deployment scaled

スケールアウト後

  • deployment
    • READY、UP-TO-DATE、AVAILABLEがそれぞれ4に変わった。
  • pod
    • podが4つに増えた。
$ sudo kubectl get all
NAME                                   READY   STATUS    RESTARTS   AGE
pod/http-deployment-7fc8f549fd-4nwxr   1/1     Running   0          6m51s
pod/http-deployment-7fc8f549fd-gkjxl   1/1     Running   0          6m51s
pod/http-deployment-7fc8f549fd-s79t7   1/1     Running   0          13s
pod/http-deployment-7fc8f549fd-t9pm4   1/1     Running   0          13s

NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/http-service   NodePort    10.100.109.122   <none>        8080:32021/TCP   6m51s
service/kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP          27h

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/http-deployment   4/4     4            4           6m51s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/http-deployment-7fc8f549fd   4         4         4       6m51s

describeの結果でも、Replicasが4つになったことが分かる。

$ sudo kubectl describe deployment/http-deployment
Name:                   http-deployment
Namespace:              default
CreationTimestamp:      Wed, 12 Jun 2019 13:26:30 +0900
Labels:                 app=http-app
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=http-app
Replicas:               4 desired | 4 updated | 4 total | 4 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
Pod Template:
  Labels:  app=http-app
  Containers:
   http-container:
    Image:        php:7.0-apache
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:
      /var/www/html from documentroot (rw)
  Volumes:
   documentroot:
    Type:          HostPath (bare host directory volume)
    Path:          /home/username/containers/web/html
    HostPathType:
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
OldReplicaSets:  <none>
NewReplicaSet:   http-deployment-7fc8f549fd (4/4 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  7m4s  deployment-controller  Scaled up replica set http-deployment-7fc8f549fd to 2
  Normal  ScalingReplicaSet  26s   deployment-controller  Scaled up replica set http-deployment-7fc8f549fd to 4

スケールダウン

スケールアウトと同じ要領でreplicas数を指定すればOK。

$ sudo kubectl scale deployments/http-deployment --replicas=2
deployment.extensions/http-deployment scaled

2つになった。

$ sudo kubectl get all
NAME                                   READY   STATUS    RESTARTS   AGE
pod/http-deployment-7fc8f549fd-4nwxr   1/1     Running   0          7m39s
pod/http-deployment-7fc8f549fd-gkjxl   1/1     Running   0          7m39s

NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/http-service   NodePort    10.100.109.122   <none>        8080:32021/TCP   7m39s
service/kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP          27h

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/http-deployment   2/2     2            2           7m39s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/http-deployment-7fc8f549fd   2         2         2       7m39s

オートスケーリングさせる方法はこちら

参考

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1