为了防止容器调度到资源不足的节点上,能够为容器指定资源最少要求量。html
为了防止容器无节制的使用 CPU、内存 等资源,能够为容器指定资源最大容许使用量。node
能够为容器指定资源请求量和资源约束量。mysql
资源通常指 CPU、内存。linux
资源请求量,指容器要求节点分配的最小容量,若是该节点可用容量小于容器要求的请求量,容器将被调度到其余合适节点。git
资源约束量,指容器要求节点限制其使用的最大容量,若是容器内存使用量超过内容约束量,容器将被杀掉,若是指定了重启策略,容器杀掉后将被重启。github
涉及的参数sql
约束量 spec.containers[].resources.limits.cpu spec.containers[].resources.limits.memory spec.containers[].resources.limits.hugepages-<size> 请求量 spec.containers[].resources.requests.cpu spec.containers[].resources.requests.memory spec.containers[].resources.requests.hugepages-<size>
示例docker
apiVersion: v1 kind: Pod metadata: name: frontend spec: containers: - name: app image: images.my-company.example/app:v4 env: - name: MYSQL_ROOT_PASSWORD value: "password" resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" - name: log-aggregator image: images.my-company.example/log-aggregator:v6 resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
K8S 中的一个 cpu 等于云平台上的 1 个 vCPU/核或裸机 Intel 处理器上的 1 个超线程。api
spec.containers[].resources.requests.cpu 为 0.5 的容器确定可以得到请求 1 CPU 的容器的一半 CPU 资源。表达式 0.1 等价于表达式 100m, 能够看做 “100 millicpu”。具备小数点(如 0.1)的请求由 API 转换为 100m;最大精度是 1m。微信
优先考虑使用 100m 的形式。
内存可使用E、P、T、G、M、K。也可使用对应的 2 的幂数:Ei、Pi、Ti、Gi、Mi、Ki。
Pod 的请求量等于内部全部容器的请求量之和。
Pod 的约束量等于内部全部容器的约束量之和。
调度程序确保所调度的 Pod 的资源请求量小于节点的容量。
即,调度程序将查找到资源可用量充足的,可用量大于请求量的节点来放置 Pod。
若是容器超过其内存最大限制,则可能会被终止。若是容器可从新启动,kubelet 将从新启动容器。
若是一个容器内存使用量超过其内存请求值,那么当节点内存不足时,容器所处的 Pod 可能被逐出。
每一个容器可能被容许也可能不被容许使用超过其 CPU 约束的处理时间。 可是,容器不会因为 CPU 使用率太高而被杀死。
spec.containers[].resources.limits.cpu 先被转换为 millicore 值,再乘以 100。其结果就是每 100 毫秒内容器可使用的 CPU 时间总量。在此期间(100ms),容器所使用的 CPU 时间不会超过它被分配的时间。
默认的配额(quota)周期为 100 毫秒。 CPU配额的最小精度为 1 毫秒。
如何获知集群资源使用状况,须要经过 metrics-server 来获取。
查看是否已安装 metrics-server,如下说明没安装
# kubectl top node Error from server (NotFound): the server could not find the requested resource (get services http:heapster:) # kubectl get pods,svc,deployments -n kube-system | grep metrics-server #
开始安装 metrics-server
git clone https://github.com/kubernetes-incubator/metrics-server cd metrics-server/ git checkout release-0.3
修改 metrics-server/deploy/1.8+/metrics-server-deployment.yaml
containers: - name: metrics-server #image: k8s.gcr.io/metrics-server/metrics-server:v0.3.6 image: registry.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6 imagePullPolicy: IfNotPresent args: - --cert-dir=/tmp - --secure-port=4443 - --metric-resolution=30s - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP - --kubelet-insecure-tls
参数说明
--metric-resolution=30s:从 kubelet 采集数据的周期; --kubelet-preferred-address-types:优先使用 InternalIP 来访问 kubelet,这样能够避免节点名称没有 DNS 解析记录时,经过节点名称调用节点 kubelet API 失败的状况(未配置时默认的状况); --kubelet-insecure-tls:kubelet 的10250端口使用的是https协议,链接须要验证tls证书。--kubelet-insecure-tls不验证客户端证书
安装
kubectl apply -f deploy/1.8+/
再次查看,须要多等一下子,确保采集到数据。
[root@master01 ~]# kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes" {"kind":"NodeMetricsList","apiVersion":"metrics.k8s.io/v1beta1","metadata":{"selfLink":"/apis/metrics.k8s.io/v1beta1/nodes"},"items":[]} [root@master01 1.8+]# kubectl top nodes NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% master01 163m 4% 2093Mi 56% master02 147m 3% 1638Mi 44% master03 151m 3% 1609Mi 43% work01 141m 3% 1084Mi 29% work02 150m 3% 1097Mi 29% work03 138m 3% 1471Mi 39% [root@master01 1.8+]# kubectl top pod NAME CPU(cores) MEMORY(bytes) mysql-0 15m 202Mi mysql-1 14m 191Mi mysql-2 13m 182Mi nfs-client-provisioner-7db698bbc9-8ph55 2m 8Mi
已经能够看到资源使用状况。
建立一个测试用命名空间
# kubectl create namespace mem-example namespace/mem-example created
建立一个最大限额 100M,但最少须要 250M 的容器
# cat memory-request-limit-2.yaml apiVersion: v1 kind: Pod metadata: name: memory-demo-2 namespace: mem-example spec: containers: - name: memory-demo-2-ctr image: polinux/stress resources: requests: memory: "50Mi" limits: memory: "100Mi" command: ["stress"] args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]
# kubectl apply -f memory-request-limit-2.yaml pod/memory-demo-2 created
查看发现建立失败
# kubectl get pod -n mem-example NAME READY STATUS RESTARTS AGE memory-demo-2 0/1 CrashLoopBackOff 3 88s
查看缘由
# kubectl get pod -n mem-example -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' memory-demo-2 Container Name: memory-demo-2-ctr LastState: map[terminated:map[containerID:docker://aaf41e exitCode:1 reason:OOMKilled ]]
其中有 reason:OOMKilled,说明超过了内存最大限额,致使了 OOM 而后被杀掉。
经过 resources.requests 和 resources.limits,能够对资源进行最少容量要求和最大容量限制,确保容器能够运行在资源充足的节点上,同时也不会因为自身占用了过多资源而影响节点上其余容器。
微信公众号:zuolinux_com