理解AWS Fargate中绑定挂载和数据卷在共享存储方面的区别

首先

如果将应用程序容器化并在AWS Fargate上运行,对于Django+Nginx的情况,需要共享静态文件,但是我对机制理解不清楚,感到困惑。事后我想明白了,但我整理了一下相关内容。

想做的事情

画一个大致结构图就是这个样子。虽然实际上用了RDS和ECR等等,但这里省略了。

test.png

在两个可用性区域内部署公共子网,使用Fargate进行负载平衡操作。
在一个任务中放置Django和Nginx的两个容器。
需要在Django和Nginx之间共享文件(实际是目录),因为在左右的Fargate之间进行了负载平衡,所以需要进行共享。

总的来说

    • タスク内のコンテナ間での共有 → バインドマウント

 

    サービス内のロードバランシングしているタスク間での共有 → データボリューム

如果任务中只有一个容器,那么就不需要进行挂载,并且如果不进行负载均衡,也不需要数据卷。

在任务中的容器之间进行共享(绑定挂载)

为了加深理解,可以试着简化一下,就是这个样子。
而且我想要在Django和Nginx中共享目录(/var/local/django)。

test1.png

详细信息请参阅以下说明,特别是“在Dockerfile内公开路径和内容到容器”的部分。

 

首先,对于每个Dockerfile,需要指定VOLUME。

# pull official base image
FROM python:3.10-slim-bullseye

# get arg
ARG APP_DIR=/usr/src/app
ARG SHARED_DIR=/var/local/django
# UIDとGIDはnginxコンテナのnginxユーザに合わせる
ARG UID=101
ARG GID=101

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV DEBIAN_FRONTEND noninteractive
ENV LANG=ja_JP.UTF-8

# set work directory
WORKDIR ${APP_DIR}

# copy
COPY ./app .
COPY ./requirements.txt .

# install dependencies
RUN apt-get update && apt-get install -y locales && \
    sed -i -E 's/# (ja_JP.UTF-8)/\1/' /etc/locale.gen && \
    locale-gen && \
    pip install --upgrade pip && \
    pip install -r requirements.txt && \
    rm requirements.txt && \
    groupadd nginx -g ${GID} && \
    useradd nginx -u ${UID} -g ${GID} --home=${APP_DIR} && \
    mkdir -p ${SHARED_DIR} && \
    chown -R nginx.nginx ${SHARED_DIR}

USER nginx

VOLUME ["${SHARED_DIR}"]
FROM nginx:1.23-alpine

# get arg
ARG SHARED_DIR=/var/local/django

# ひょっとしたらmkdir不要かもしれない。
RUN rm /etc/nginx/conf.d/default.conf && \
    mkdir -p ${SHARED_DIR} && chown nginx:nginx ${SHARED_DIR}

COPY nginx.conf /etc/nginx/conf.d

VOLUME ["${SHARED_DIR}"]

在AWS的任务定义的volumes部分中,将名称定义为efs并进行绑定挂载。

  "volumes": [
    {
      "name": "efs",
    }
  ]

我不在乎名字,但之后我会进行efs的设置,所以我提前这么做了。

然后是容器定义

[
    {
      "name" : "nginx",
      },
      "mountPoints" : [
        {
          "containerPath" : "/var/local/django",
          "sourceVolume" : "efs"
        }
      ],
      "portMappings" : [
        {
          "protocol" : "tcp",
          "hostPort" : 80,
          "containerPort" : 80
        }
      ]
    },
    {
      "name" : "django",
      },
      "command" : ["gunicorn", "-w", "3", "-b", ":8000", "--access-logfile", "-", "--capture-output", "--log-level", "debug", "mysite.wsgi:application"],
      "mountPoints" : [
        {
          "containerPath" : "/var/local/django",
          "sourceVolume" : "efs"
        }
      ]
    }

顺便说一句,我经常看到同时写上两个portMappings的例子,但只在Nginx方面写就可以了。此外,别忘了Django和Nginx的配置。

Django的一旁

SHARED_DIR = '/var/local/django'
STATIC_ROOT = os.path.join(SHARED_DIR, 'static')

请原生中国人对以下内容进行释义:Nginx side.

  location /static/ {
    alias /var/local/django/static/;
  }

在服务内共享的任务之间(数据量)

如果容器之间可以共享,那么接下来需要在任务之间进行共享。
有几种方法可行,作为terraform用户的我参考了以下使用EFS的方法。当然也可以从AWS控制台操作。

 

在上述情况下,为每个可用区设置了两个aws_efs_mount_target,但是由于缺少EFS访问点,我添加了以下内容。

resource "aws_efs_access_point" "access" {
  file_system_id = aws_efs_file_system.efs.id
}

最后

由于无法公开完整的产品,所以只能提供一些片段式的信息,不知道到底能传达多少,但愿能够稍微帮到一些忙。

另外,在容器之间共享时,也许使用 S3 来设计而非绑定挂载会更符合 AWS 的风格。

广告
将在 10 秒后关闭
bannerAds