05. レプリケーションと水平自動スケーリング
| # 手動スケーリング
$ kubectl scale deployment nextjs-example --replicas=3
# オートスケーリング(CPU使用率50%で自動増減)
$ kubectl autoscale deployment nextjs-example --min=1 --max=5 --cpu-percent=50
|
DeploymentにてPodのレプリカ数を定義する。
| k8s/app-deployment.yaml |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 | apiVersion: apps/v1
kind: Deployment
metadata:
labels:
io.kompose.service: app
name: app
spec:
replicas: 3
selector:
matchLabels:
io.kompose.service: app
template:
metadata:
labels:
io.kompose.service: app
spec:
containers:
- env:
- name: DATABASE_URL
value: postgresql://postgres:postgres@db:5432/todo
- name: HOSTNAME
value: "0.0.0.0"
image: 192.168.11.42:8085/nextjs-todo-example:latest
name: app
ports:
- containerPort: 3000
protocol: TCP
restartPolicy: Always
|
Serviceにてtype: NodePortを設定する。これによりServiceが複数のPodにリクエストを割り振るようになる。
| k8s/app-service.yaml |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | apiVersion: v1
kind: Service
metadata:
labels:
io.kompose.service: app
name: app
spec:
type: NodePort
ports:
- name: "3000"
port: 3000
targetPort: 3000
selector:
io.kompose.service: app
|
なおKubernetesにおいて、Serviceは3種類のポートを持っている。
| フィールド |
値 |
意味 |
| port |
3000 |
Service自身のポート(クラスター内部用) |
| targetPort |
3000 |
転送先のPodのポート |
| nodePort |
未指定 |
ノードで公開するポート |
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | # リソースを適用する
$ kubectl apply -f ./k8s/
# Podsが3つ動作していることを確認する
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
app-585544ffb9-88rqm 1/1 Running 0 18m
app-585544ffb9-qtmkr 1/1 Running 0 33m
app-585544ffb9-tfl74 1/1 Running 0 32m
db-668bb7bcbb-4m5xc 1/1 Running 0 33m
# ServiceのURLを確認する
$ minikube service app --url
http://***.***.***.***:31035
|
kubectl port-forward service/app 3000:3000は動作確認用のコマンドで
Podのポートとホストのポートを紐づける。Podが複数ある場合、1つが自動で選ばれるため、レプリケーションの動作確認には向かない。
minikube service app --urlはServiceに紐づくURLを取得するため、Serviceのロードバランシングの動作確認に使える。

アプリケーションにアクセスできることを確認したら、Podを1つ削除する。
| # Podを1つ削除する
$ kubectl delete pod app-585544ffb9-88rqm
pod "app-585544ffb9-88rqm" deleted from default namespace
# KubernetesがDeploymentの定義に従うようにPodを起動させていることを確認する
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
app-585544ffb9-qr79z 1/1 Running 0 3s
app-585544ffb9-qtmkr 1/1 Running 0 55m
app-585544ffb9-tfl74 1/1 Running 0 54m
db-668bb7bcbb-4m5xc 1/1 Running 0 55m
|
引き続きアプリケーションにアクセスできることを確認する。
水平自動スケーリング
水平自動スケーリングを行うにはHorizontalPodAutoscaler(以下HPAとする)のリソースを定義する。
HPAは設定値に従ってPodを増減させる。
| k8s/app-hpa.yaml |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: app
minReplicas: 1
maxReplicas: 3
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50 # 全Podの平均CPU使用量が requests の50% を超えたらレプリカ数を増やす
behavior:
scaleUp:
stabilizationWindowSeconds: 0 # 0秒間高負荷が続いたらスケールアップする (デフォルトは0秒)
scaleDown:
stabilizationWindowSeconds: 60 # 60秒間低負荷が続いたらスケールダウンする (デフォルトは5分)
|
ただしHPAは使用率を計算するための基準値が必要となる。
\[
\mathrm{CPU使用率} = \frac{\mathrm{実際の使用量}}{\mathrm{requests}}
\]
基準値はDeploymentで定義する。
| k8s/app-deployment.yaml |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 | apiVersion: apps/v1
kind: Deployment
metadata:
labels:
io.kompose.service: app
name: app
spec:
selector:
matchLabels:
io.kompose.service: app
template:
metadata:
labels:
io.kompose.service: app
spec:
containers:
- env:
- name: DATABASE_URL
value: postgresql://postgres:postgres@db:5432/todo
- name: HOSTNAME
value: "0.0.0.0"
image: 192.168.11.42:8085/nextjs-todo-example:latest
name: app
ports:
- containerPort: 3000
protocol: TCP
resources:
requests:
cpu: "4m" # Pod1個で0.004コアを確保する
limits:
cpu: "10m" # Pod1個で最大0.01コアを確保する
restartPolicy: Always
|
requestsの値はkubectl top podsで計測して、適切な値に変更する。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | $ minikube addons enable metrics-server
💡 metrics-server is an addon maintained by Kubernetes. For any concerns contact minikube on GitHub.
You can view the list of minikube maintainers at: https://github.com/kubernetes/minikube/blob/master/OWNERS
▪ Using image registry.k8s.io/metrics-server/metrics-server:v0.8.0
🌟 The 'metrics-server' addon is enabled
# 結構時間がかかる
$ kubectl top pods
error: Metrics API not available
$ kubectl top pods
error: Metrics API not available
$ kubectl top pods
error: Metrics API not available
$ kubectl top pods
NAME CPU(cores) MEMORY(bytes)
app-585544ffb9-qr79z 1m 33Mi
app-585544ffb9-qtmkr 1m 33Mi
app-585544ffb9-tfl74 1m 33Mi
db-668bb7bcbb-4m5xc 4m 20Mi
# 以下でも良い
$ watch -n 0.5 kubectl top pods
# これでも良い
$ kubectl get pods -w
|
appについて、以下のことがわかった。
\[
\mathrm{appの定常時の使用量} = 1m
\]
HPAのリソース定義より、HPAのスケールアップ閾値は以下で求められる。
\[
\begin{align}
\mathrm{HPAのスケールアップ閾値} &= \mathrm{Deploymentのrequests} \times \frac{\mathrm{HPAのaverageUtilization}}{100} \\
&= 4m \times \frac{50}{100} \\
&= 2m
\end{align}
\]
appの定常時の使用量は1mであるから、limitsは10mとすると上限は定常時の10倍までになる。
| $ kubectl apply -f ./k8s/
$ watch -n 0.5 kubectl top pods
|
Webブラウザでアプリケーションにアクセスし、F5を連打するとPodが増えることがわかる。
放置するとPodが減ることがわかる。