如何让 Postgres 容器与亚马逊 EFS 共享数据?

问题描述

我有一个集群,它有 2 个实例。两个实例都有 Postgres 容器,它的卷链接到弹性文件系统访问点作为卷。

我将两个实例的卷映射到 /var/lib/postgresql/data,但容器没有共享其数据。

这是我的配置

docker-compose.yml

version: "3.0"
services:
    front:
        image: 540744822643.dkr.ecr.ap-southeast-1.amazonaws.com/front:latest
        links:
            - app:app.plasgate.com
        networks:
            - app
        container_name: front
        environment:
            - NODE_OPTIONS=--max-old-space-size=2048
        ports:
            - "8080:80"
        logging:
            driver: awslogs
            options:
                awslogs-group: sms-gateway
                awslogs-region: ap-southeast-1
                awslogs-stream-prefix: "front"
    app:
        image: 540744822643.dkr.ecr.ap-southeast-1.amazonaws.com/plasgate:latest
        links:
            - jasmin:jasmin
            - db:db
        networks:
            - app
        container_name: app
        environment:
            - PYTHONUNBUFFERED=1
            - PYTHONIOENCODING=UTF-8
        restart: on-failure:10
        ports:
            - "5000:5000"
        logging:
            driver: awslogs
            options:
                awslogs-group: sms-gateway
                awslogs-region: ap-southeast-1
                awslogs-stream-prefix: "app"
    Nginx:
        image: 540744822643.dkr.ecr.ap-southeast-1.amazonaws.com/Nginx:latest
        links:
            - app:app
            - front:front
        container_name: Nginx
        networks:
            - app
        environment:
            API_HOST: "service.wpdevelop.xyz"
            API_PORT: 5000
            FRONT_HOST: "customer.wpdevelop.xyz"
            FRONT_PORT: 8080

        ports:
            - "80:80"
            - "443:443"
        logging:
            driver: awslogs
            options:
                awslogs-group: sms-gateway
                awslogs-region: ap-southeast-1
                awslogs-stream-prefix: "Nginx"
    db:
        image: 540744822643.dkr.ecr.ap-southeast-1.amazonaws.com/postgres:latest
        volumes:
            - postgres:/var/lib/postgresql/data:rw
        restart: on-failure:10
        networks:
            - app
        environment:
            POSTGRES_PASSWORD: "xxx@2020"
            POSTGRES_USER: webadmin
            POSTGRES_DB: smsgwdev
        ports:
            - "5432:5432"
        logging:
            driver: awslogs
            options:
                awslogs-group: sms-gateway
                awslogs-region: ap-southeast-1
                awslogs-stream-prefix: "db"
    redis:
        image: 540744822643.dkr.ecr.ap-southeast-1.amazonaws.com/radis:latest
        container_name: redis
        restart: on-failure:10
        networks:
            - app
        ports:
            - "6379:6379"
        logging:
            driver: awslogs
            options:
                awslogs-group: sms-gateway
                awslogs-region: ap-southeast-1
                awslogs-stream-prefix: "redis"
volumes:
    postgres:
networks:
    app:
        driver: bridge

ecs-params.yml

version: 1
task_deFinition:
    family: sms-gateway
    ecs_network_mode: bridge
    services:
        front:
            essential: true
            cpu_shares: 100
            mem_limit: 2147483648
            healthcheck:
                test: ["CMD-SHELL","curl -f http://localhost || exit 1"]
                interval: 5s
                timeout: 10s
                retries: 3
                start_period: 30s
        app:
            essential: false
            cpu_shares: 100
            mem_limit: 2147483648
            healthcheck:
                test: ["CMD-SHELL","curl -f http://localhost:5000 || exit 1"]
                interval: 5s
                timeout: 10s
                retries: 3
                start_period: 30s
            depends_on:
                - container_name: db
                  condition: HEALTHY
        Nginx:
            essential: false
            cpu_shares: 100
            mem_limit: 2147483648
            healthcheck:
                test: ["CMD-SHELL","curl -f http://localhost || exit 1"]
                interval: 5s
                timeout: 10s
                retries: 3
                start_period: 30s
        db:
            essential: false
            cpu_shares: 100
            mem_limit: 2147483648
            healthcheck:
                test: pg_isready -U webadmin -d smsgwdev
                interval: 5s
                timeout: 10s
                retries: 2
                start_period: 30s
        redis:
            essential: false
            cpu_shares: 100
            mem_limit: 2147483648
            healthcheck:
                test: ["CMD-SHELL","redis-cli","ping"]
                interval: 5s
                timeout: 10s
                retries: 2
                start_period: 30s

    efs_volumes:
        - name: postgres
          filesystem_id: fs-a4aa73e4
          transit_encryption: ENABLED
          access_point: fsap-007405b3e9bc7bc2f

有人请教我如何让两个 Postgres 容器使用相同的 pgdata?

解决方法

这里有很多东西需要打开 IMO。

首先,在 EFS 上运行 Postgres 并不是一个好主意。我认为如果您需要一些快速且在测试环境中负载非常低的东西,这很好,但 EFS 不是数据库引擎的正确后端。其次,在 2 个容器之间共享 EFS 共享是一个更糟糕的主意。这种设置是不允许的,因为每个数据库都将同时获得对相同数据文件的非仲裁访问,这不是 Postgres 的工作方式。

第二,您没有明确地调用它,但是您是否使用 ecs-cli 来部署它?如果是这样,我的建议是查看我们 (AWS) 与 Docker 一起引入的替代机制,该机制依赖于 new Docker Compose capabilities to deploy to the Cloud (e.g. ECS)ecs-cli 的新版本称为 Copilot,它不再支持 Docker。请注意,新的 Docker Compose 集成目前不需要单独的 ecs-params 文件(尽管有讨论要引入一个文件)并且依赖于 docker compose 文件本身中的 x-aws- 扩展。

第三,无论这是否是一个好主意(它不是!)在 this 示例之后并受其启发,下面的简单组合允许您部署 2 个共享相同的 Postgres 容器数据目录:

version: '3.4'
services:
  db1:
    container_name: db1
    image: postgres:latest
    environment:
      - POSTGRES_USER=me
      - POSTGRES_PASSWORD=mypassword
    volumes:
      - my-vol:/var/lib/postgresql/data
  db2:
    depends_on:
      - db1
    container_name: db2
    image: postgres:latest
    environment:
      - POSTGRES_USER=me
      - POSTGRES_PASSWORD=mypassword
    volumes:
      - my-vol:/var/lib/postgresql/data
  app:
    container_name: app
    image: nginx
volumes:
  my-vol:

如果您在 ECS 上下文 (see the blog for more details) 中 docker compose up,您将获得 3 个 ECS 服务(1 个应用程序/nginx 和 2 个 DB 服务),其中 2 个 DB 服务坚持使用相同的 EFS 访问观点。同样,这只是一个学术示例,用于证明工作的 docker compose 文件。我不建议在任何有意义的部署中使用它。

[更新]:我刚刚注意到您在上面的撰写中只有 1 个 postgres。因此,我假设您有两个单独的撰写文件,其中一个 postgres 数据库坚持使用相同的文件系统。我上面说的所有内容仍然适用,但请注意有 a limitation that will prevent you to even technically deploy this scenario