nekop's blog

OpenShift / JBoss / WildFly / Infinispanの中の人 http://twitter.com/nekop

ThinkPad T470sにFedora 27インストール

会社からクリスマスプレゼントでThinkPad T470sをもらったので翌日出社して受け取ってFedora 27をインストールしてメインマシンのスイッチ。スペックはIntel Core i7-7600U 2.8GHz 4 cores, 16GB mem, NVMe SSD 256GB。

前回の記録はFedora 24インストール

いつも通りHow to create and use Live USBCUIlivecd-toolsを使ってUSB起動したけどなぜかgrub/images/pxeboot/vmlinuzという存在していないパスを参照していて起動しなかった。いい機会だったのでごちゃまぜUSBメモリの運用をやめて、新しいUSBメモリGUImediawriterを使ってインストール専用USBメモリを作成してふつうにインストールした。

セットアップの流れはあまり変わってない。今回のセットアップでの変更点がいくつか。

  • メインブラウザとしてFirefoxではなくChrome(実験)
    • Firefoxのセットアップやspice-xpiインストールなどはスキップ
  • Emacsのsemiとwanderlustをpackage-installするようにした
  • Bluejeansはchrome extensionになったのでrpmパッケージはもういらない
  • Emacsのフォントがなぜか明朝になったのでとりあえず以下の設定を入れた。あとでフォント変えるかも。
(cond
 (window-system (set-default-font "DejaVu Sans Mono-8")
                (set-fontset-font (frame-parameter nil 'font)
                                  'japanese-jisx0208
                                  '("VL ゴシック" . "unicode-bmp"))))

Chromechrome://settings/でOn Startup -> Continue where you left offに設定してセッションを復元するように。あとはcp /usr/share/applications/google-chrome.desktop ~/.local/share/applications/してExecに--auth-server-whitelistを指定してKerberos認証の有効化。.desktopファイルをまるっとコピーしているのが若干微妙なんだけど差分だけ書けるようなもっとスマートな方法あるのかな。

OpenShift Container Platform 3.7をAWS上にシングルノードでセットアップする

OpenShift 全部俺 Advent Calendar 2017

OpenShiftをAWSでセットアップするリファレンスアーキテクチャやCloudFormationやデプロイスクリプトなどはいろいろ用意されていますが、本番構成向けのもったりした構成です。AWS上でのテスト用にシングルノードセットアップを使いたい場合があるので、手順を書いておきます。

VPC, Internet Gateway, Subnetなどは事前に作成する前提です。EC2 Instanceは以下のものを利用しました。

  • AMI: RHEL-7.4_HVM_GA-20170724-x86_64-1-Access2-GP2
  • Instance Type: m4.xlarge (4 vCPU, 16G mem)
  • Disk: 80GB
  • Tag: kubernetes.io/cluster/foo=owned
  • Elastic IP付与

Elastic IPの生IPやながーいホスト名は扱いづらいので、Route 53でmasterのホスト名とワイルドカードアプリケーションドメインをCNAMEもしくはAレコードで上記Elastic IPに設定します。

AWS上でKubernetesを利用する場合はkubernetes.io/cluster/<clusterid>タグが必要になります。設定しないと同一アカウント内の複数のKubernetesクラスタがEBSの奪い合いなどリソースの処理で競合して面白いことが起きます。

Security Groupは適切に設定してください。Allow All設定でAllowAllPasswordIdentityProviderの設定であれば当然ですがビットコイン掘られます。

起動したら前回と同じように以下のようなスクリプトを用意してsudoで流し込みます。

RHSM_USERNAME=
RHSM_PASSWORD=
RHSM_POOLID=
OPENSHIFT_VERSION=3.7

subscription-manager register --username=$RHSM_USERNAME --password=$RHSM_PASSWORD
subscription-manager attach --pool $RHSM_POOLID
subscription-manager repos --disable=*
subscription-manager repos \
     --enable=rhel-7-server-rpms \
     --enable=rhel-7-server-extras-rpms \
     --enable=rhel-7-server-optional-rpms \
     --enable=rhel-7-server-rh-common-rpms \
     --enable=rhel-7-fast-datapath-rpms \
     --enable=rhel-7-server-ose-$OPENSHIFT_VERSION-rpms

yum install chrony wget git net-tools bind-utils iptables-services bridge-utils nfs-utils sos sysstat bash-completion lsof tcpdump yum-utils yum-cron docker atomic-openshift-utils -y
sed -i 's/DOCKER_STORAGE_OPTIONS=/DOCKER_STORAGE_OPTIONS="--storage-driver overlay2"/' /etc/sysconfig/docker-storage
systemctl enable chronyd docker
systemctl start chronyd docker
reboot

再度接続したらansibleの準備です。

$ ssh-keygen
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ sudo mkdir -p /etc/aws
$ sudo cat <<EOF > /etc/aws/aws.conf
[Global]
Zone = ap-northeast-1c
EOF
$ sudo vi /etc/ansible/hosts

Ansibleのhostsファイルはこんな感じです。AWSやOpenStackなどのクラウド環境上ではホスト定義にopenshift_hostnameパラメータを定義してはいけません。Kubernetesのクラウドインテグレーションは内部ホスト名を要求するので、オーバーライドするといろいろエラーになります。

[OSEv3:children]
masters
etcd
nodes

[OSEv3:vars]
ansible_ssh_user=ec2-user
ansible_become=true
deployment_type=openshift-enterprise
openshift_master_identity_providers=[{'name': 'htpasswd', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/master/htpasswd'}]
os_sdn_network_plugin_name=redhat/openshift-ovs-multitenant
openshift_node_kubelet_args={'kube-reserved': ['cpu=100m,memory=100Mi'], 'system-reserved':['cpu=100m,memory=100Mi'], 'eviction-hard': [ 'memory.available<4%', 'nodefs.available<4%', 'nodefs.inodesFree<4%', 'imagefs.available<4%', 'imagefs.inodesFree<4%' ], 'eviction-soft': [ 'memory.available<8%', 'nodefs.available<8%', 'nodefs.inodesFree<8%', 'imagefs.available<8%', 'imagefs.inodesFree<8%' ], 'eviction-soft-grace-period': [ 'memory.available=1m30s', 'nodefs.available=1m30s', 'nodefs.inodesFree=1m30s', 'imagefs.available=1m30s', 'imagefs.inodesFree=1m30s' ]}
openshift_disable_check=memory_availability,disk_availability

openshift_master_cluster_public_hostname=master.example.com
openshift_master_default_subdomain=apps.example.com

openshift_cloudprovider_kind=aws
openshift_cloudprovider_aws_access_key="{{ lookup('env','AWS_ACCESS_KEY_ID') }}"
openshift_cloudprovider_aws_secret_key="{{ lookup('env','AWS_SECRET_ACCESS_KEY') }}"
openshift_clusterid=foo

[masters]
master.example.com

[etcd]
master.example.com

[nodes]
master.example.com openshift_node_labels="{'region': 'infra'}" openshift_schedulable=true

インストールを行なえばEBS PVのダイナミックプロビジョニングもセットアップされている状態になっているはずです。

export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
ansible-playbook -vvvv /usr/share/ansible/openshift-ansible/playbooks/byo/config.yml | tee -a openshift-install-$(date +%Y%m%d%H%M%S).log
reboot

OpenShiftでメモリでオートスケールをしてみる

OpenShift 全部俺 Advent Calendar 2017

まだAlpha機能ですが、CPUではなくメモリ利用量でオートスケールを設定することができます。

https://docs.openshift.org/latest/dev_guide/pod_autoscaling.html#pod-autoscaling-memory

先に重要な点を書いておきますが、このメモリ利用量とはcgroupsのmemory.usage_in_bytesであり、これはbuff/cacheを含みます。実際には解放できるディスクキャッシュなども使用中としてレポートされ、キャッシュが活用されている限りメモリ利用は常に高い状態をキープしますので、メモリベースのオートスケールは現状あまり使い物にならないと思います。

まずはドキュメントの通り以下の設定をmaster-config.yamlへ反映してmasterを再起動します。

apiServerArguments:
  runtime-config:
  - apis/autoscaling/v2alpha1=true

いつものRubyのサンプルを作成してrequests.memoryに64Miを指定します。

$ oc new-project test-memhpa
$ oc new-app https://github.com/nekop/hello-sinatra
$ oc set resources dc/hello-sinatra --requests=memory=64Mi
$ cat <<EOF | oc create -f -
apiVersion: autoscaling/v2alpha1
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-memory 
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: DeploymentConfig
    name: hello-sinatra
  minReplicas: 1 
  maxReplicas: 10 
  metrics:
  - type: Resource
    resource:
      name: memory
      targetAverageUtilization: 50 
EOF

作成したHPAを再度取得するとAlpha機能であるため内容のほとんどは以下のようにアノテーション内に格納されていることがわかります。

$ oc get hpa hpa-memory -o yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  annotations:
    autoscaling.alpha.kubernetes.io/conditions: '[{"type":"AbleToScale","status":"True","lastTransitionTime":"2017-12-25T02:36:07Z","reason":"ReadyForNewScale","message":"the
      last scale time was sufficiently old as to warrant a new scale"},{"type":"ScalingActive","status":"True","lastTransitionTime":"2017-12-25T02:36:07Z","reason":"ValidMetricFound","message":"the
      HPA was able to succesfully calculate a replica count from memory resource utilization
      (percentage of request)"},{"type":"ScalingLimited","status":"False","lastTransitionTime":"2017-12-25T02:36:07Z","reason":"DesiredWithinRange","message":"the
      desired replica count is within the acceptible range"}]'
    autoscaling.alpha.kubernetes.io/current-metrics: '[{"type":"Resource","resource":{"name":"memory","currentAverageUtilization":24,"currentAverageValue":"16576512"}}]'
    autoscaling.alpha.kubernetes.io/metrics: '[{"type":"Resource","resource":{"name":"memory","targetAverageUtilization":50}}]'
  creationTimestamp: 2017-12-25T02:35:37Z
  name: hpa-memory
  namespace: test-memhpa
  resourceVersion: "4241124"
  selfLink: /apis/autoscaling/v1/namespaces/test-memhpa/horizontalpodautoscalers/hpa-memory
  uid: 4a2e8f4e-e91c-11e7-b3cf-001a4a40dc83
spec:
  maxReplicas: 10
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: DeploymentConfig
    name: hello-sinatra
status:
  currentReplicas: 1
  desiredReplicas: 1

初期状態はメモリ16Mi利用しています。

$ oc adm top pod
NAME                    CPU(cores)   MEMORY(bytes)   
hello-sinatra-2-d9ft8   0m           16Mi

32MBのファイルを作ってcatしてディスクキャッシュに載せてみます。

$ oc rsh dc/hello-sinatra sh -c "dd if=/dev/zero of=/tmp/32mb bs=32M count=1; cat /tmp/32mb"

少し経過すると、メトリクスに反映されました。

$ oc adm top pod
NAME                    CPU(cores)   MEMORY(bytes)   
hello-sinatra-2-d9ft8   5m           48Mi            

HPAによるスケールアウトがトリガーされ、Podが2つに増えました。

$ oc get pod
NAME                    READY     STATUS    RESTARTS   AGE
hello-sinatra-2-b9hxt   1/1       Running   0          16s
hello-sinatra-2-d9ft8   1/1       Running   0          5m
$ oc adm top pod
NAME                    CPU(cores)   MEMORY(bytes)   
hello-sinatra-2-d9ft8   0m           48Mi            
hello-sinatra-2-b9hxt   0m           15Mi   

動作に必要なメモリが足りなくなりそうな場合にスケールアウト、というのが欲しいところですが、今のところはこのように動作に不可欠ではない解放されるメモリもカウントされてオートスケールされてしまいますので、使い道はかなり限定されそうです。

OpenShiftのmaster-config.yamlやnode-config.yamlの書式

OpenShift 全部俺 Advent Calendar 2017

たとえばmaster-config.yamlをカスタマイズしたい場合にどうやって記述すればいいのかなどを調べたい場合があります。

以下に項目がさらっと書かれたドキュメントがあり、さらっと把握するのには役立ちますが、やはりyaml形式の場合にどのように書いたら良いというようなガイドはありません。

https://docs.openshift.org/latest/install_config/master_node_configuration.html

どこを見れば良いかというとソースコードです。OpenShiftはGo言語で記述されており、yaml形式の設定ファイルはこの定義とダイレクトにマップしています。

https://github.com/openshift/origin/blob/master/pkg/cmd/server/api/v1/types.go

たとえばkubernetesMasterConfig.controllerArgumentsは以下のように定義されています。

ControllerArguments ExtendedArguments `json:"controllerArguments"`

ExtendedArgumentsはkeyがstring、valueが[]stringのmapです。

type ExtendedArguments map[string][]string

つまり記述はこんな感じになります。

kubernetesMasterConfig:
  controllerArguments:
    foo:
    - bar
    - baz
    hoge:
    - "10"

string型であるので、数値などはクオートしないといけません。

Go言語の型とyaml形式のちょっとした知識は必要となりますが、難しいものではないので、このapi/v1/types.goを参照すればよい、ということさえわかっていればすぐ調べられます。

ちなみに各コンポーネントのデフォルト値を調べたい場合はソースツリーからoptions.goというファイルをリストするとたぶんわかります。

OpenShiftのディスク利用傾向

OpenShift 全部俺 Advent Calendar 2017

OpenShiftやKubernetesではどのようにディスクが使われ、どのくらいのディスクを必要とするのでしょうか。PVを割り当てて利用する分は自明ですが、それ以外はどのようになっているでしょうか。

コンテナイメージにVolumeが定義されている場合、oc new-appはEmptyDirを割り当てるようになっています。

EmptyDirは実際にはコンテナホストのファイルシステムの以下の位置にマップされています。

/var/lib/origin/openshift.local.volumes/pods/${POD_ID}/volumes/kubernetes.io~empty-dir/${MOUNT_PATH}

実際にEmptyDirへの書き込みをやってみましょう。

$ oc new-project test-volume
$ cat <<EOF | oc new-build --dockerfile=- --to=sleep
FROM registry.access.redhat.com/rhel
RUN mkdir /testvol && chmod 777 /testvol
VOLUME /testvol
CMD tail -f /dev/null
EOF
$ oc new-app sleep

初期状態のディスクはこのような状態です。Dockerのストレージドライバはoverlay2なので、コンテナのストレージは/var/lib/docker以下となります。

$ df -H
Filesystem                             Size  Used Avail Use% Mounted on
/dev/mapper/rhel_unused--221--68-root   54G   43G   12G  80% /
$ sudo du -hs /var/lib/docker /var/lib/origin
8.6G    /var/lib/docker
8.8G    /var/lib/origin

EmptyDirに1GBのsushiを書き込んでみます。/var/lib/originにファイルが作成されました。

$ oc volume dc/sleep
deploymentconfigs/sleep
  empty directory as sleep-volume-1
    mounted at /testvol
$ oc rsh dc/sleep ls -la /testvol
total 0
drwxrwsrwx. 2 root 1000200000  6 Dec 22 04:39 .
drwxr-xr-x. 1 root root       21 Dec 22 04:39 ..
$ oc rsh dc/sleep dd if=/dev/zero of=/testvol/sushi bs=1M count=1K
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 4.07493 s, 263 MB/s
$ oc rsh dc/sleep ls -l /testvol
-rw-r--r--. 1 1000200000 1000200000 1073741824 Dec 22 04:40 sushi
$ sudo find /var/lib/origin -name sushi
/var/lib/origin/openshift.local.volumes/pods/efe5f789-e6d4-11e7-9665-001a4a40dc83/volumes/kubernetes.io~empty-dir/sleep-volume-1/sushi
$ sudo du -hs /var/lib/docker /var/lib/origin
8.6G    /var/lib/docker
9.8G    /var/lib/origin

EmptyDirの定義を消してみます。EmptyDirではなくコンテナ内のディスクに書いているので、今度は/var/lib/dockerに1GBのsushiが置かれました。

$ oc volume dc/sleep --remove --confirm
deploymentconfig "sleep" updated
$ oc volume dc/sleep
deploymentconfigs/sleep
$ oc rsh dc/sleep dd if=/dev/zero of=/testvol/sushi bs=1M count=1K
$ oc rsh dc/sleep ls -l /testvol
total 1048576
-rw-r--r--. 1 1000200000 1000200000 1073741824 Dec 22 04:52 sushi
$ sudo find /var/lib/docker -name sushi
/var/lib/docker/volumes/46ddab197dfdb73aeea844898d903b6ecfe487e8abbda4724639f77e57f20836/_data/sushi
$ sudo du -hs /var/lib/docker /var/lib/origin
9.6G    /var/lib/docker
8.8G    /var/lib/origin

また、コンテナのログもログドライバがjson-fileにしろjournaldにしろ、コンテナホスト /var のディスク領域を消費します。数十のコンテナアプリケーションがログを出力することになるので、ログの量も大量です。

コンテナはこのようにコンテナホストの/var以下のディスク領域をとにかく大量に消費するため、ディスクフル障害となりやすいので注意してください。コンテナのこれらのディスク利用量を制限する簡単な方法は今のところありません1し、コンテナがどのくらいのデータやログを出力するの事前予測も簡単ではありません。ノードリソースにもよりますが、/varには200GB+程度のディスクを割りあてるなど、余裕を持ったディスク割り当てにしておくというのが今のところ最も有効な障害の予防手段となります。


  1. OpenShiftにはvolumeConfig.localQuota.perFsGroupxfs_quotaで制限をかける仕組みがあります

OpenShiftでUID指定されているコンテナをデプロイする

OpenShift 全部俺 Advent Calendar 2017

OpenShift上で動作するコンテナにはOpenShift側で採番されたUIDが割り当てられて、そのUIDで動作します。そのため、rootや特定のUIDでファイルにアクセスしたりすることを期待しているコンテナは動作しません。

とはいえ、DockerfileでUSER指定されているふつうのコンテナを動かしたいときもあります。そんなときにはSCCのnonrootを利用します。

https://docs.openshift.org/latest/admin_guide/manage_scc.html

このOpenShiftのSCC (Security Context Constraints)はKubernetesのPSP (Pod Security Policies)のベースとなっています。何度見てもプレイステーションポータブルって読んでしまいます。

https://kubernetes.io/docs/concepts/policy/pod-security-policy/

sccのデフォルトは以下のようになっています。

$ oc get scc
NAME               PRIV      CAPS      SELINUX     RUNASUSER          FSGROUP     SUPGROUP    PRIORITY   READONLYROOTFS   VOLUMES
anyuid             false     []        MustRunAs   RunAsAny           RunAsAny    RunAsAny    10         false            [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
hostaccess         false     []        MustRunAs   MustRunAsRange     MustRunAs   RunAsAny    <none>     false            [configMap downwardAPI emptyDir hostPath persistentVolumeClaim projected secret]
hostmount-anyuid   false     []        MustRunAs   RunAsAny           RunAsAny    RunAsAny    <none>     false            [configMap downwardAPI emptyDir hostPath nfs persistentVolumeClaim projected secret]
hostnetwork        false     []        MustRunAs   MustRunAsRange     MustRunAs   MustRunAs   <none>     false            [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
nonroot            false     []        MustRunAs   MustRunAsNonRoot   RunAsAny    RunAsAny    <none>     false            [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
privileged         true      [*]       RunAsAny    RunAsAny           RunAsAny    RunAsAny    <none>     false            [*]
restricted         false     []        MustRunAs   MustRunAsRange     MustRunAs   RunAsAny    <none>     false            [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]

sccには適用順があります。nonrootにはpriorityがセットされていないので、まずpriorityをセットする必要があります。

https://docs.openshift.org/latest/architecture/additional_concepts/authorization.html#scc-prioritization

$ oc patch scc nonroot -p "priority: 2"

これで準備はOKです。まずはUSERを指定したコンテナをデプロイして、割り当てられたUIDで動作していることを確認します。

$ cat <<EOF | oc new-build --dockerfile=- --to=sleep
FROM registry.access.redhat.com/rhel
RUN useradd -u 1001 -g 0 -d / -s /sbin/nologin default
USER 1001
CMD tail -f /dev/null
EOF
$ oc new-app sleep

scc, UIDの割り当てとランタイムのUIDを確認してみます。

$ oc describe project test-nonroot | grep scc
            openshift.io/sa.scc.mcs=s0:c14,c4
            openshift.io/sa.scc.supplemental-groups=1000190000/10000
            openshift.io/sa.scc.uid-range=1000190000/10000
$ oc describe pod sleep-1-5hgvn | grep scc
        openshift.io/scc=restricted
$ oc rsh dc/sleep id
uid=1000190000 gid=0(root) groups=0(root),1000190000

USER指定の1001ではないUIDとなっています。

scc nonrootをdefaultサービスアカウントに与えて再デプロイしてみます。

$ oc adm policy add-scc-to-user nonroot -z default
$ oc rollout latest sleep
$ oc describe pod sleep-2-hhzfd | grep scc
        openshift.io/scc=nonroot
$ oc rsh dc/sleep id
uid=1001(default) gid=0(root) groups=0(root)

きちんとUIDが変更されていますね。

UIDの変更方法を紹介しましたが、基本的にはコンテナイメージガイドラインに沿って、割り当てられたUIDで動作するようコンテナを作成することが推奨されます。

https://docs.openshift.org/latest/creating_images/guidelines.html

sccの適用は基本的にはセキュリティリスクとなりますので、利用は最小限となるようにしましょう。nonrootは比較的安全なsccですが、NFS PVへのアクセスなど、UIDがキーとなるセキュリティコントロールがあるのでやはりデフォルトのrestrictedより劣ります。また、rootが許可されるprivilegedやanyuidはセキュリティ的には最低ですので、これらが適用されるコンテナのイメージは必ず信頼されるもののみとしてください。自社できちんとメンテナンスしているもの、Red Hatなどのベンダーから正式に提供されているもの、などです。

OpenShiftのResource requestとlimit

OpenShift 全部俺 Advent Calendar 2017

最初はどのように指定したらいいかわかりづらいという質問がよくあるKubernetesのResource requestとlimitです。

https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

Podにはこのような定義でResource request, limit (リソース要求、制限)を記述します。

resources:
  requests:
    cpu: 100m
    memory: 64Mi
  limits:
    memory: 64Mi

CPUもメモリもrequestsを記述しないと、CPUはゼロ割り当てでまったく動かなくても構わない、メモリについてはいつメモリ不足で終了されても構わない、という意味になります。そのようなアプリケーションでない限り、これらは必ず指定してください。

スケジューラはrequestsを元にスケジューリングを行います。4CPU coresのノードにrequests.cpuが4のPodを割り当てたら、あとは上記のどうでもいいPod以外はそのノードにはスケジューリングされません。このPodは4CPU使えることが保証されます。

CPUについてはlimitsを指定すると、ノードにCPUが空いていてもそれ以上は利用できない、という意味になります。指定しなければ無制限です。普通のアプリケーションにとってはCPUが空いているのに使えないというのは基本的にデメリットしかありませんので、その場合はCPUについてはlimitsを指定する必要性はありません。もちろん、limitsが必要なケースはあり、たとえばユーザがビットコインを掘ることが想定されるような場合はlimits指定が必要です。空いているCPUが他のPodに利用されていても、requests.cpuが指定されているPodがCPUを使おうとすればもちろんrequests.cpu分はそちらに割り当てられるので、この空いているCPU利用は他のPodで確保されているCPU利用を阻害することはありません。

メモリについてはlimitsを指定しない場合(無制限)、もしくはrequestsよりlimitsを大きく指定する場合は、requestsを超えたメモリ使用量になった瞬間から、いつでもメモリ不足のため終了されても構わない、という状態になります。この「いつでもメモリ不足のため終了されても構わない」というアプリケーションはそれほど多くはないと思いますので、メモリについては基本的にrequests/limitsは同値指定で動作に十分な量を指定することが多いと思います。メモリ利用がlimits.memoryに達した場合はPodはoom-killerに殺されます。

というわけで、基本的にはrequests.cpuとrequests.memory == limits.memoryを指定しましょう。

あとはこの記事では解説しませんが、クラスタ管理者はノード保護のためkube-reservedとかevictionは適切に設定しましょう。

https://kubernetes.io/docs/tasks/administer-cluster/out-of-resource/