不行的
虽然 HugePages 的申请方式与默认的内存相差不多,但是它实际上是操作系统单独管理的特殊资源,Linux 会在 /proc/meminfo 中单独展示 HugePages 的相关数据,而 Kubernetes 也会认为大页是不同于内存的独立资源。
另外,在设计方案中,大页资源请求是固定的,不支持过量使用(overcommit),也不是为可能有多种尺寸的场景设计的。
我们认为,应用程序试图使用多个巨大页面尺寸的情况很少。
所以:
你可能不得不根据你的节点设置不同pod规格,例如通过污点
将有助于识别特定资源。
问题解决了。但是原因具体原因不能确定。如果有相同情况,可以按照这个思路排查看看。
我们服务器是arm架构,但是jdk没有使用arm架构的,替换了jdk版本后文件正常删除了。
NM_CONTROLLED
的值:修改文件/etc/sysconfig/network-scripts/ifcfg-eth0
的内容:
NM_CONTROLLED="no" //是否允许Network Manager管理,设置为no
默认允许Network Manager管理DNS,所以首先设置为no,然后操作DNS设置
修改DNS可以有如下两种方案:
1.修改网卡设置:
在/etc/sysconfig/network-scripts/ifcfg-eth0
中修改内容:
PEERDNS="yes"
DNS1="xxx.xxx.xxx.xxx"
DNS2="xxx.xxx.xxx.xxx"
这种设置方案是以网卡中设置的DNS为主,resolv.conf中按照网卡设置的DNS内容自动生成,以后想修改DNS,必须修改网卡中的设置才不会在服务器重启之后出现DNS设置失效的问题。
2、直接修改/etc/resolv.conf
的值:
需要注意的是,若要使直接修改的DNS内容不会在服务器重启之后丢失,需要设置网卡中PEERDNS
的值为no
:
nameserver xxx.xxx.xxx.xxx
nameserver xxx.xxx.xxx.xxx
service network restart
集群中的每个 Pod 都有一个 endpoint,即 Pod 的 IP 和 targetPort。
service是将流量发送给endpoint。
可以通过以下命令查看:
kubectl get endpoints
ingress 将 service 的 endpoint 配置给内置的 nginx。
好处:使用 Endpoints API 来绕过 kube-proxy,如会话亲和性和自定义负载平衡算法。 消除了一些不必要的开销,例如 iptables DNAT 的 conntrack 条目。
最终,port 和 targetPort 都会转换成容器端口,也就是targetPort
,所以都可以。
从容器的角度出发,限制容器使用的CPU和内存,是通过cgroup来实现的,目前kubernetes的QoS只能管理CPU和内存,所以kubernetes现在也是通过对cgroup的配置来实现QoS管理的。
在kubernetes中,每个Pod都有个QoS标记,QoS的英文全称为 Quality of Service
,中文名为服务质量
,它取决于用户对服务质量的预期,也就是期望的服务质量。对于Pod来说,服务质量体现在两个指标上,一个指标是CPU,另一个指标是内存。在实际运行过程中,当NODE节点
上内存资源紧张的时候,kubernetes根据Pod具有的不同QoS标记,采取不同调度和驱逐策略。
Kubernetes 创建 Pod 时就给它指定了下列一种 QoS 类:
如果满足下面条件,将会指定 Pod 的 QoS 类为 Burstable:
1、当 NODE节点上内存资源不够的时候,QoS级别是BestEffort的Pod会最先被kill掉;当NODE节点上内存资源充足的时候,QoS级别是BestEffort的POD可以使用NODE节点上剩余的所有内存资源。
2、当NODE节点上内存资源不够的时候,如果QoS级别是BestEffort的Pod已经都被kill掉了,那么会查找QoS级别是Burstable的POD,并且这些POD使用的内存已经超出了requests设置的内存值,这些被找到的POD会被kill掉;当NODE节点上内存资源充足的时候,QoS级别是Burstable的POD会按照requests和limits的设置来使用。
3、当NODE节点上内存资源不够的时候,如果QoS级别是BestEffort和Burstable的Ppod都已经被kill掉了,那么会查找QoS级别是Guaranteed的POD,并且这些POD使用的内存已经超出了limits设置的内存值,这些被找到的POD会被kill掉;当NODE节点上内存资源充足的时候,QoS级别是Burstable的POD会按照requests和limits的设置来使用。
详细参考:配置Pod的服务质量(QoS)
我们先了解下容器在 Kubernetes 环境中的终止流程:
preStop Hook
,将会执行。terminationGracePeriodSeconds
内 (默认 30s) 还未完全停止,就发送 SIGKILL 信号强制杀死进程。SIGTERM
信号要实现优雅终止,务必在业务代码里面处理下 SIGTERM 信号,参考 处理 SIGTERM 代码示例 ) 。
别让 shell 导致收不到 SIGTERM 信号
如果容器启动入口使用了脚本 (如 CMD ["/start.sh"]),业务进程就成了 shell 的子进程,在 Pod 停止时业务进程可能收不到 SIGTERM 信号,因为 shell 不会自动传递信号给子进程。更详细解释请参考 为什么我的容器收不到 SIGTERM 信号 ?
合理使用 preStop Hook
若你的业务代码中没有处理 SIGTERM 信号,或者你无法控制使用的第三方库或系统来增加优雅终止的逻辑,也可以尝试为 Pod 配置下 preStop,在这里面实现优雅终止的逻辑,示例:
lifecycle:
preStop:
exec:
command:
- /clean.sh
在某些极端情况下,Pod 被删除的一小段时间内,仍然可能有新连接被转发过来,因为 kubelet 与 kube-proxy 同时 watch 到 pod 被删除,kubelet 有可能在 kube-proxy 同步完规则前就已经停止容器了,这时可能导致一些新的连接被转发到正在删除的 Pod,而通常情况下,当应用受到 SIGTERM 后都不再接受新连接,只保持存量连接继续处理,所以就可能导致 Pod 删除的瞬间部分请求失败。
这种情况下,我们也可以利用 preStop 先 sleep 一小下,等待 kube-proxy 完成规则同步再开始停止容器内进程:
lifecycle:
preStop:
exec:
command:
- sleep
- 5s
如果需要的优雅终止时间比较长 (preStop + 业务进程停止可能超过 30s),可根据实际情况自定义 terminationGracePeriodSeconds
,避免过早的被 SIGKILL
杀死:
使用kubectl describe pod
来查看具体的报错原因:
1、使用如下命令查看 Pod 状态:
$ kubectl get pods
2、可以使用 kubectl describe pod
命令来查询问题 Pod 的更多信息,比如:
kubectl describe pod nginx-deployment-1006230814-6winp
查看Events:
段,可以看到具体失败的原因。
你还可以看到与 Pod 相关的近期事件。系统通过指示第一次和最后一次看到事件以及看到该事件的次数来压缩多个相同的事件。From
标明记录事件的组件,SubobjectPath
告诉你引用了哪个对象(例如 Pod 中的容器), Reason
和Message
告诉你发生了什么。
如果需要列出所有事件,可使用命令:
kubectl get events
但是,需要注意的是,事件是区分名字空间的。 如果你对某些名字空间域的对象(比如 my-namespace 名字下的 Pod)的事件感兴趣, 你需要显式地在命令行中指定名字空间:
kubectl get events --namespace=my-namespace
详细kubernetes pods故障排查,可参考:Kubernetes(k8s)应用程序自测与调试