理解AWS Fargate中绑定挂载和数据卷在共享存储方面的区别
首先
如果将应用程序容器化并在AWS Fargate上运行,对于Django+Nginx的情况,需要共享静态文件,但是我对机制理解不清楚,感到困惑。事后我想明白了,但我整理了一下相关内容。
想做的事情
画一个大致结构图就是这个样子。虽然实际上用了RDS和ECR等等,但这里省略了。
在两个可用性区域内部署公共子网,使用Fargate进行负载平衡操作。
在一个任务中放置Django和Nginx的两个容器。
需要在Django和Nginx之间共享文件(实际是目录),因为在左右的Fargate之间进行了负载平衡,所以需要进行共享。
总的来说
-
- タスク内のコンテナ間での共有 → バインドマウント
- サービス内のロードバランシングしているタスク間での共有 → データボリューム
如果任务中只有一个容器,那么就不需要进行挂载,并且如果不进行负载均衡,也不需要数据卷。
在任务中的容器之间进行共享(绑定挂载)
为了加深理解,可以试着简化一下,就是这个样子。
而且我想要在Django和Nginx中共享目录(/var/local/django)。
详细信息请参阅以下说明,特别是“在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 的风格。