概要
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を設置する。
<?php echo gethostname() . "\n"; ?>
Deploymentを定義
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を定義
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