摘要:一些公共服务组件在追求性能过程中,与业务耦合太紧,造成在制作基础镜像时,都会把这些基础组件都打包进去,因此当业务镜像启动后,容器里面一大堆进程,这让Kubernetes对Pod的管理存在很大隐患。为了让业务容器瘦身,更是为了基础组件自身的管理更独立和方便,将基础组件从业务镜像中剥离并DaemonSet容器化部署。然而一些基础组件Agent与业务Pod之间通过共享内存的方式进行通信,同一Node中跨Pod的共享内存方案是首先要解决的问题。为什么要将公共基础组件Agent进行DaemonSet部署自研的公共基础组件,比如服务路由组件、安全组件等,通常以进程方式部署在Node上并同时为Node上所有的业务提供服务,微服务及容器化之后,服务数量成百上千的增长,如果以sidecar或者打包到业务Image中继续Per Pod Per Agent的方式部署, 那么基础组件的Server端的压力可能也会成百上千的增长,风险是很大的。因此,我们希望能以DaemonSet方式部署这些组件的Agents。 先说说Kubernetes大行其道的今天,如果不将这些基础组件从业务Pod中剥离,存在哪些问题:
将基础组件Agents从业务Pod中剥离,以上的问题都能解决了,架构上的解耦带来的好处无需多言。而且我们可以通过Kubernetes管理这些基础组件Agents了,享受其自愈、滚动升级等好处。 Linux共享内存机制然而,理想很美好,现实很残酷。首先要解决的问题是,有些组件Agent与业务Pod之间是通过共享内存通信的,这跟Kubernetes&微服务的最佳实践背道而驰。 大家都知道,Kubernetes单个Pod内是共享IPC的,并且可以通过挂载Medium为Memory的EmptyDir Volume共享同一块内存Volume。 首先我们来了解一下Linux共享内存的两种机制:
其中,System V共享内存历史悠久,一般的UNIX系统上都有这套机制;而POSIX共享内存机制接口更加方便易用,一般是结合内存映射mmap使用。 mmap和System V共享内存的主要区别在于:
POSIX共享内存是基于tmpfs来实现的。实际上,更进一步,不仅PSM(POSIX shared memory),而且SSM(System V shared memory)在内核也是基于tmpfs实现的。 从这里可以看到tmpfs主要有两个作用:
虽然System V与POSIX共享内存都是通过tmpfs实现,但是受的限制却不相同。也就是说 /proc/sys/kernel/shmmax只会影响SYS V共享内存,/dev/shm只会影响Posix共享内存 。实际上,System V与Posix共享内存本来就是使用的两个不同的tmpfs实例(instance)。 SYS V共享内存能够使用的内存空间只受/proc/sys/kernel/shmmax限制;而用户通过挂载的/dev/shm,默认为物理内存的1/2。
同一Node上夸Pod的共享内存方案基础组件Agents DaemonSet部署后,Agents和业务Pod分别在同一个Node上不同的Pod,那么Kubernetes该如何支持这两种类型的共享内存机制呢?
当然,安全性上做出了牺牲,但在非容器化之前IPC的隔离也是没有的,所以这一点是可以接受的。 灰度上线对于集群中的存量业务,之前都是将Agents与业务打包在同一个docker image,因此需要有灰度上线方案,以保证存量业务不受影响。
$ 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
总结在高并发业务下,尤其还是以C/C++代码实现的基础组件,经常会使用共享内存通信机制来追求高性能,本文给出了Kubernetes Pod间Posix/SystemV共享内存方式的折中方案,以牺牲一定的安全性为代价,请知悉。当然,如果微服务/容器化改造后,基础服务的Server端确定不会有压力,那么建议以SideCar Container方式将基础服务的Agents与业务Container部署在同一Pod中,利用Pod的共享IPC特性及Memory Medium EmptyDir Volume方式共享内存。 (责任编辑:IT) |