KubernetesのResourceQuotaを設定した場合の挙動確認のメモ。IBM Cloud Private-CE 3.1で確認。
準備
メモリに負荷をかけるためのイメージを用意する。コンテナを起動するとstressコマンドで256MBメモリを消費する。
FROM ubuntu:16.04
RUN apt-get update && \
apt-get install -y stress && \
rm -rf /var/lib/apt/lists/*
CMD ["stress", "-m","1", "--vm-bytes" ,"256M","--vm-hang","0","-q"]
イメージをビルドする。
docker build -t sotoiwa540/stress:1.0 .
レジストリにアップロードする。ここではDockerHubにアップロードする。
docker login
docker push sotoiwa540/stress:1.0
デプロイ確認
今回はsugiというNamespaceにデプロイするのでnamespaceを作成する。
kubectl create ns sugi
マニフェストを作成してデプロイする。
apiVersion: apps/v1
kind: Deployment
metadata:
name: stress
namespace: sugi
spec:
selector:
matchLabels:
app: stress
replicas: 10
template:
metadata:
labels:
app: stress
spec:
containers:
- name: stress
image: sotoiwa540/stress:1.0
imagePullPolicy: Always
kubectl apply -f stress-deploy.yaml
Podを確認する。
$ kubectl get deploy -n sugi
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
stress 10 10 10 10 2m
$ kubectl get po -n sugi
NAME READY STATUS RESTARTS AGE
stress-9bd965f55-5z27g 1/1 Running 0 2m
stress-9bd965f55-98rqf 1/1 Running 0 2m
stress-9bd965f55-9bfqd 1/1 Running 0 2m
stress-9bd965f55-brt6p 1/1 Running 0 2m
stress-9bd965f55-gqnwp 1/1 Running 0 2m
stress-9bd965f55-hm7kx 1/1 Running 0 2m
stress-9bd965f55-lwtns 1/1 Running 0 2m
stress-9bd965f55-t2fj9 1/1 Running 0 2m
stress-9bd965f55-t7hrn 1/1 Running 0 2m
stress-9bd965f55-wttz6 1/1 Running 0 2m
$
リソースの使用状況を確認する。
$ kubectl top pod -n sugi
NAME CPU(cores) MEMORY(bytes)
stress-9bd965f55-5z27g 0m 257Mi
stress-9bd965f55-98rqf 0m 258Mi
stress-9bd965f55-9bfqd 0m 258Mi
stress-9bd965f55-brt6p 0m 257Mi
stress-9bd965f55-gqnwp 0m 258Mi
stress-9bd965f55-hm7kx 0m 257Mi
stress-9bd965f55-lwtns 0m 257Mi
stress-9bd965f55-t2fj9 0m 257Mi
stress-9bd965f55-t7hrn 0m 258Mi
stress-9bd965f55-wttz6 0m 257Mi
$
一旦デプロイメントを削除する。
kubectl delete -f stress-deploy.yaml
requests.memory
はじめにrequests.memoryを試す。
apiVersion: v1
kind: ResourceQuota
metadata:
name: requests-memory
namespace: sugi
spec:
hard:
requests.memory: 2G
kubectl apply -f requests-memory-quota.yaml
確認する。
$ kubectl describe quota requests-memory -n sugi
Name: requests-memory
Namespace: sugi
Resource Used Hard
-------- ---- ----
requests.memory 0 2G
$
この状態でsterssをデプロイする。Podが作成されない。Pending状態になるわけではなく、そもそもPodがスケジュールされないことに注意。
$ kubectl apply -f stress-deploy.yaml
deployment.apps/stress created
$ kubectl get deploy -n sugi
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
stress 10 0 0 0 27s
$ kubectl get po -n sugi
No resources found.
$
各コンテナに.resources.requests.memory
が設定されていないと、Podをスケジュールできないため。
Deploymentを削除する。
kubectl delete -f stress-deploy.yaml
.resources.requests.memory
を追加したバージョンのDeployment定義を作成する。
apiVersion: apps/v1
kind: Deployment
metadata:
name: stress-requests
namespace: sugi
spec:
selector:
matchLabels:
app: stress
replicas: 10
template:
metadata:
labels:
app: stress
spec:
containers:
- name: stress
image: sotoiwa540/stress:1.0
imagePullPolicy: Always
resources:
requests:
memory: "300Mi"
デプロイする。今度はPodが作成され、Namespaceへのrequests制限が2GBなので、300MB*6つのPodしか作成されていないことが確認できる。
$ kubectl apply -f stress-requests-deploy.yaml
deployment.apps/stress-requests created
$ kubectl get deploy -n sugi
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
stress-requests 10 6 6 6 33s
$ kubectl get po -n sugi
NAME READY STATUS RESTARTS AGE
stress-requests-c75fbc58c-284md 1/1 Running 0 39s
stress-requests-c75fbc58c-7p6v7 1/1 Running 0 39s
stress-requests-c75fbc58c-7wmc8 1/1 Running 0 39s
stress-requests-c75fbc58c-gnn67 1/1 Running 0 39s
stress-requests-c75fbc58c-m4xnr 1/1 Running 0 39s
stress-requests-c75fbc58c-n7h8d 1/1 Running 0 40s
$
DeploymentとResourceQuotaを削除する。
kubectl delete -f stress-requests-deploy.yaml
kubectl delete -f requests-memory-quota.yaml
limits.memory
続いてlimits.memoryを試す。
apiVersion: v1
kind: ResourceQuota
metadata:
name: limits-memory
namespace: sugi
spec:
hard:
limits.memory: 2G
kubectl apply -f limits-memory-quota.yaml
確認する。
$ kubectl describe quota limits-memory -n sugi
Name: limits-memory
Namespace: sugi
Resource Used Hard
-------- ---- ----
limits.memory 0 2G
$
先ほど使用したDeployment定義をデプロイしてみる。Podが作成されない。
$ kubectl apply -f stress-deploy.yaml
deployment.apps/stress created
$ kubectl apply -f stress-requests-deploy.yaml
deployment.apps/stress-requests created
$ kubectl get deploy -n sugi
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
stress 10 0 0 0 30s
stress-requests 10 0 0 0 7s
$ kubectl get po -n sugi
No resources found.
$
コンテナに.resources.limits.memory
が設定されていないと、Podをスケジュールできないため。
Deploymentを削除する。
kubectl delete -f stress-deploy.yaml
kubectl delete -f stress-requests-deploy.yaml
.resources.limits.memory
を追加したバージョンのDeployment定義を作成する。
apiVersion: apps/v1
kind: Deployment
metadata:
name: stress-limits
namespace: sugi
spec:
selector:
matchLabels:
app: stress
replicas: 10
template:
metadata:
labels:
app: stress
spec:
containers:
- name: stress
image: sotoiwa540/stress:1.0
imagePullPolicy: Always
resources:
limits:
memory: "300Mi"
この定義でデプロイする。Podが作成される。
$ kubectl apply -f stress-limits-deploy.yaml
deployment.apps/stress-limits created
$ kubectl get deploy -n sugi
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
stress-limits 10 6 6 1 9s
$ kubectl get po -n sugi
NAME READY STATUS RESTARTS AGE
stress-limits-8548966749-jkwfr 1/1 Running 0 18s
stress-limits-8548966749-l5wtz 1/1 Running 0 18s
stress-limits-8548966749-mshg5 1/1 Running 0 18s
stress-limits-8548966749-v9l92 1/1 Running 0 18s
stress-limits-8548966749-vwtbb 1/1 Running 0 18s
stress-limits-8548966749-zh4g8 1/1 Running 0 19s
$
6つしか作成されない。実際のメモリ使用量としては、あと1つPodを作成できるはずである。
$ kubectl top pod -n sugi
NAME CPU(cores) MEMORY(bytes)
stress-limits-8548966749-jkwfr 1m 257Mi
stress-limits-8548966749-l5wtz 1m 258Mi
stress-limits-8548966749-mshg5 1m 257Mi
stress-limits-8548966749-v9l92 1m 257Mi
stress-limits-8548966749-vwtbb 0m 257Mi
stress-limits-8548966749-zh4g8 1m 257Mi
$
つまりResourceQuotaに対してlimitsを設定するというのは、実際のメモリ使用量に対して制限を掛けているわけではなく、requestsの場合と同様に、単に各コンテナで設定されているlimitsの合計をチェックしているだけである。
補足
各コンテナでRequestsとLimitsを定義する代わりに、LimitRangeでデフォルト値を定義することもできる。
Configure Default Memory Requests and Limits for a Namespace