【k8s】多pod间通信之共享内存

进程间通信一直是工程实现经常遇到的场景,比如说数据处理的进程将结果发送给日志进程记录;亦或者多个数据处理进程,在处理数据的的时候,会有一部分配置需要共享,这样以来这些配置文件一个node只存一份即可,并且在内存中查询肯定比redis快的;再或者就是处理大型数据集的时候,需要一个控制进程和多个数据线程,控制线程进行数据的分片和整合,数据进程进行无脑计算,这个时候控制线程和数据线程是需要进行通信的。

进程间通信方式也有很多,这次我们介绍一种最快的方式--共享内存,快的原因简单说就是这些进程间数据传递不再涉及到内核,即不再通过执行进入内核的系统调用来传递彼此的数据。

共享内存实现原理

裸金属共享内存通信

arduino 复制代码
// 1.查看共享内存段
ipcs -m
ipcrm -m shmid

// 2.创建共享内存
/* shmget() returns the identifier of the shared memory segment associated with the value of the argument key. */
/* size equal to the value of size rounded up to a multiple of PAGE_SIZE  */
/* PC_CREAT | IPC_EXCL  */
int shmget(key_t key, size_t size, int shmflg);

// 3.挂接共享内存
/* shmat() attaches the shared memory segment identified by shmid to the address space of the calling process.  */
/* If shmaddr is NULL, the system chooses a suitable (unused) address at which to attach the segment. */
/* If shmaddr isn't NULL and SHM_RND is specified in shmflg, the attach occurs at the address equal 
   to shmaddr rounded down to the nearest multiple of SHMLBA. Otherwise shmaddr must be a page-aligned 
   address at which the attach occurs. */
void *shmat(int shmid, const void *shmaddr, int shmflg);

// 4.去关联共享内存
int shmdt(const void *shmaddr);

// 5.以cmd操纵共享内存
/* shmctl() performs the control operation specified by cmd on the shared memory segment whose 
   identifier is given in shmid. */
/* cmd: 
   IPC_RMID: Mark the segment to be destroyed.
   IPC_SET:  Write the values of some members of the shmid_ds structure pointed to by arg.buf 
             to the kernel data structure associated with this shared memory segment
   IPC_STAT: Copy information from the kernel data structure associated with shmid 
             into the shmid_ds structure pointed to by buf.
   */
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

简单写一个demo,分为两个进程,一个是reader进程,一个writer进程。writer进程负责初始化创建一段共享内存,reader进程启动后不断轮询共享内存是否创建好,如果创建好就可以将数据读取出来。

arduino 复制代码
//Makefile:

.PHONY:all
all:reader writer
 
writer:writer.c 
	gcc -o $@ $^
reader:reader.c 
	gcc -o $@ $^
 
.PHONY:clean
clean:
	rm -f reader writer

//common.h

#ifndef _COMMON_H__
#define _COMMON_H__
 
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
 
#define PATHNAME "zhihushm"
#define PROJ_ID  0x6666

#endif

//writer.c

#include "writer.h"
static char *shm_addr = NULL;
int create_shm()
{
	key_t key = ftok(PATHNAME, PROJ_ID);
	if(key < 0)
	{
		perror("ftok");
		return -1;
	}
	int shmid = shmget(key, 4096, IPC_CREAT | IPC_EXCL | 0666);
	if(shmid < 0)
	{
		perror("shmget");
		return -2;
	}
	shm_addr = shmat(shmid, NULL, 0);
	return 0;
}

void write_something()
{
	int i = 0;
	while (i < 4096)
	{
		shm_addr[0] = i % 128;
		i++;
		sleep(1);
	}	
}

int main()
{
	int ret = create_shm();
	if (ret < 0)
	{
		return -1;
	}
	write_something();
	return 0;
}

//reader.c

#include "writer.h"
static char *shm_addr = NULL;
int init()
{
	key_t key = ftok(PATHNAME, PROJ_ID);
	if(key < 0)
	{
		perror("ftok");
		return -1;
	}

	int shmid = shmget(key, 4096, IPC_CREAT);
	if(shmid < 0)
	{
		perror("shmget");
		return -2;
	}
	shm_addr = shmat(shmid, NULL, 0);
	return 0;
}

void read_something()
{
	int i = 0;
	while (i < 4096)
	{
		printf("we get %c\n", shm_addr[0]);
		sleep(1);
	}	
}

int main()
{
	int ret = init();
	while (ret < 0)
	{
		ret = init();
	}
	read_something();
	return 0;

}

k8s中pod间共享内存通信

好啦,现在请出这章的主角---多pod共享内存通信,而实现的关键就在各pod同时挂载/dev/shm即可,详细方案如下图:

这样,我们简单把上面的reader和writer两个进程分别容器化,再由k8s调度起来,并起多个reader pod和一个writer pod,来看看是否多个reader pod可以读到writer写的数据,以达到每一个Node上数据只有一份,多pod共享的目的。

先写两个Dockerfile:

bash 复制代码
//reader.Dockerfile

FROM centos

ADD  .  /home/

RUN chmod 777 /home/reader

ENTRYPOINT ["/home/reader"]  

//writer.Dockerfile

FROM centos

ADD  .  /home/

RUN chmod 777 /home/writer

ENTRYPOINT ["/home/writer"] 

再build出镜像并运行:

bash 复制代码
docker build -t reader:v1 . -f reader.Dockerfile

docker build -t writer:v1 -f writer.Dockerfile

docker run -ti --name writer -v /dev/shm:/dev/shm --net=host --ipc=host writer:v1 bash

docker run -ti --name reader -v /dev/shm:/dev/shm --net=host --ipc=host reader:v1 bash

既然起两个docker看来是可以通信的了,那我们再写两个yaml文件并用k8s部署出来:

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: huhuxx
  name: huhuxx
spec:
  selector:
    matchLabels:
      app: huhuxx
  template:
    metadata:
      labels:
        app: huhuxx
    spec:
      hostNetwork: true
      hostIPC: true
      containers:
      - name: huhuxx
        image: reader:v4
        imagePullPolicy: Never
        volumeMounts:
        - mountPath: /dev/shm
          name: shm
      volumes:
      - name: shm
        hostPath:
          path: /dev/shm
          type: Directory

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: huhuxx
  name: huhuxx
spec:
  selector:
    matchLabels:
      app: huhuxx
  template:
    metadata:
      labels:
        app: huhuxx
    spec:
      hostNetwork: true
      hostIPC: true
      containers:
      - name: huhuxx
        image: writer:v4
        imagePullPolicy: Never
        volumeMounts:
        - mountPath: /dev/shm
          name: shm
      volumes:
      - name: shm
        hostPath:
          path: /dev/shm
          type: Directory

查看同一node上的,writer pod和其中两个reader pod:

成啦,虽然实现比较粗糙,毕竟demo嘛,证明这条路是可以走通哒。

Reference

Kubernetes中Pod间共享内存方案 - 腾讯云开发者社区-腾讯云 (tencent.com)

进程间通信------共享内存(Shared Memory)_victory_523的博客-CSDN博客_共享内存

shmget() - Unix, Linux System Call (tutorialspoint.com)

docker警告:WARNING: IPv4 forwarding is disabled. Networking will not work._杰哥的技术杂货铺的博客-CSDN博客

k8s(kubernetes)拉取本地镜像部署节点_赛博朋克2078的博客-CSDN博客_k8s拉取本地镜像

相关推荐
Q_192849990614 分钟前
基于Spring Boot的九州美食城商户一体化系统
java·spring boot·后端
ZSYP-S43 分钟前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring
Yuan_o_1 小时前
Linux 基本使用和程序部署
java·linux·运维·服务器·数据库·后端
程序员一诺2 小时前
【Python使用】嘿马python高级进阶全体系教程第10篇:静态Web服务器-返回固定页面数据,1. 开发自己的静态Web服务器【附代码文档】
后端·python
DT辰白2 小时前
如何解决基于 Redis 的网关鉴权导致的 RESTful API 拦截问题?
后端·微服务·架构
thatway19893 小时前
AI-SoC入门:15NPU介绍
后端
陶庵看雪3 小时前
Spring Boot注解总结大全【案例详解,一眼秒懂】
java·spring boot·后端
Q_19284999063 小时前
基于Spring Boot的图书管理系统
java·spring boot·后端
ss2734 小时前
基于Springboot + vue实现的汽车资讯网站
vue.js·spring boot·后端
一只IT攻城狮4 小时前
华为云语音交互SIS的使用案例(文字转语音-详细教程)
java·后端·华为云·音频·语音识别