Pod里的容器如何设置IP?

2024-01-28 10:19:11 浏览数 (2)

背景

最近遇到一个docker compose部署的产品(旧版本)想部署到k8s中,而该产品应用的多个容器都在docker compose中设置了ip地址,镜像里的应用配置也是配置的这些预设ip,容器之间通过预设IP进行通信。

但是该产品的云化已经在最新版本中完成,并做了大量修改。现在希望对那个旧版本以最小成本部署到k8s中就行,也就是不想动产品应用的镜像仅仅修改部署方式

产品应用的docker compose定义

代码语言:javascript复制
version: "3.4"
services:
  db:
    image: "db"
    container_name: "db"
    restart: always
    networks:
      internal:
        ipv4_address: 169.254.253.2
  app:
    image: "app"
    container_name: "app"
    depends_on:
      - db
    network_mode:
      "service:db"
  app1:
    image: "app1"
    container_name: "app1"
    depends_on:
      - app
    networks:
      internal:
        ipv4_address: 169.254.253.7
  app2:
    image: "app2"
    container_name: "app2"
    depends_on:
      - db
    restart: always
    networks:
      internal:
        ipv4_address: 169.254.253.11
networks:
  internal:
    external: true
  • 所有容器都连接到外部创建的一个网络internal,这个网络定义了子网范围,这些容器能够互相通信
  • app容器使用db的网络,共享network namespace

如何部署到K8S中

  1. 如果每个容器部署到单独的Pod中,那么Pod之间通信就只能通过service或者pod的cluster IP。
    • 使用service就需要更改调用地址
    • 使用pod的cluster IP,就意味着需要指定pod的cluster IP为docker compose里的预设IP。这需要配置CNI,但是k8s环境是客户的,不方便修改
  2. 如果把所有容器部署到一个Pod里,网络修改的影响范围就小了。

Pod网络:在k8s中,pod的所有容器都在同一个network namespace,只分配了一个cluster IP。无法为每个容器设置单独的IP地址。

方案一:修改容器配置文件里的调用地址

通过挂载configmap去覆盖包含预设IP的配置文件。

由于存在硬编码预设IP的情况,无法修改编译产物,此方案不适用。

方案二:所有容器部署到同一个Pod,给容器单独设置IP

  • 前面提过,在pod中是无法为容器单独设置IP地址的。这里想到个取巧的方法。
  • 给容器的lo网络接口设置多IP,让所有docker compose里的预设IP都指向localhost,这样所有容器就能通过这些预设IP进行通信。并且在Pod中,这个操作对所有容器可见。

给lo网络接口设置多IP

  1. 通过ip addr查看网络接口信息
  2. 给lo网络接口添加一个 IP 地址 ip addr add 169.254.253.2/24 dev lo scope host
    • scope host: 这表示该 IP 地址的范围是主机(host),即这是一个本地回环地址。这样的地址只在本地计算机上可见,不会通过网络接口发送到物理网络。
  3. 查看是否生效

现在,可以通过169.254.253.2访问到localhost。

将这部分操作,放到Pod的initContainer里

代码语言:javascript复制
      initContainers:
        - name: init-network
          image: xxx
          imagePullPolicy: Always
          securityContext:
            privileged: true
          command: ["/bin/bash","-c"]
          args: ["ip addr add 169.254.253.2/24 dev lo scope host && ip addr add 169.254.253.3/24 dev lo scope host && ip addr add 169.254.253.4/24 dev lo scope host && ip addr add 169.254.253.5/24 dev lo scope host && ip addr add 169.254.253.6/24 dev lo scope host && ip addr add 169.254.253.7/24 dev lo scope host && ip addr add 169.254.253.12/24 dev lo scope host"]

到此,所有产品应用镜像不用修改,也能通过之前的预设IP进行通信。

方案缺点

  • 无法对单个容器进行扩缩容
  • 因为在同一个network namespace中,所有容器不能端口冲突
  • 产品容器里的预设IP不能和k8s内部网段冲突

Post Views: 6

0 人点赞