业务容器中存在一大堆进程,我们在为Pod申请资源(cpu/mem request and limit)时,不仅要考虑业务应用本身的资源消耗,还要考虑这些基础组件的资源消耗。而且一旦某些Agent有Bug,比如内存泄漏,这将导致Pod牵连被重建,甚至Cgroup OOM在kill进程时,可能将业务进程kill了。
违背了Kubernetes&微服务的部署最佳实践:Per Process Per Contaienr,并且业务进程在前台运行,使其与容器共生死,不然这将导致Kubernetes无法根据业务进程状态关联到容器状态,进而进行高可用管理。
一个Node上运行10个Pod,那么就会有x10的基础组件数量在Node上。没有容器化之前,一个Node只要部署一个组件进程即可,容器化之后,集群中组件Agents数量要几十倍的增长,如果业务进行了微服务拆分,这个指数会更大,这些基础组件服务端是否能承受比以往高几十倍上百倍的通信请求,这是未知的。
如果你要全网升级某个基础组件Agent,那你可能会疯掉,你需要重新打所有业务镜像,然后全网业务要进行灰度升级。因为一个Agent的升级,导致你不得不重建业务Pod。你可能会说,基础组件Agents都会有自己的热升级方案,我们通过它们的方案升级就好了呀,那你将引入很大麻烦:Agents的热升级因为无法被Kubernetes感知,将引发Kubernetes中集群中的数据不一致问题,那就真的要回到虚拟机或者物理机部署的玩法了。当然,这样的需求,我们也想过通过Operator也实现,但代价太大了,而且很不CloudNative!
POSIX共享内存(shmopen()、shmunlink())
System V共享内存(shmget()、shmat()、shmdt())
sysv shm是持久化的,除非被一个进程明确的删除,否则它始终存在于内存里,直到系统关机;
mmap映射的内存在不是持久化的,如果进程关闭,映射随即失效,除非事先已经映射到了一个文件上;
/dev/shm 是Linux下sysv共享内存的默认挂载点。
用于SYSV共享内存,还有匿名内存映射;这部分由内核管理,用户不可见;
用于POSIX共享内存,由用户负责mount,而且一般mount到/dev/shm;依赖于CONFIG_TMPFS。
POSIX共享内存与SYS V共享内存在内核都是通过tmpfs实现,但对应两个不同的tmpfs实例,相互独立。
通过/proc/sys/kernel/shmmax可以限制SYS V共享内存的最大值,通过/dev/shm可以限制POSIX共享内存的最大值(所有之和)。
同一Node上夸Pod的共享内存方案
$ kubectl label node $nodeName AgentsDaemonSet=YES
$ kubectl taint node $nodeName AgentsDaemonSet=YES:NoSchedule
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: demo-agent
namespace: kube-system
labels:
k8s-app: demo-agent
spec:
selector:
matchLabels:
name: demo-agent
template:
metadata:
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
labels:
name: demo-agent
spec:
tolerations:
- key: "AgentsDaemonSet"
operator: "Equal"
value: "YES"
effect: "NoSchedule"
hostNetwork: true
hostIPC: true
nodeSelector:
AgentsDaemonSet: "YES"
containers:
- name: demo-agent
image: demo_agent:1.0
volumeMounts:
- mountPath: /dev/shm
name: shm
resources:
limits:
cpu: 200m
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
volumes:
- name: shm
hostPath:
path: /dev/shm
type: Directory