使用 GitHub Actions 和 S3 将 Django 完整的 CI-CD 流程迁移到 AWS
本指南涵盖了使用 Amazon Beanstalk 和 GitHub Actions 为 Django 项目设置 CI-CD 工作流所需的所有步骤。
示例项目链接:https://github.com/vlntsolo/django-cicd
目录
在我们开始之前,首先什么是 CI-CD 流程?
尽管与编译后的应用程序相比,Django 代码不需要任何构建步骤,但每次需要部署新功能或修复错误时,手动重新上传代码可能会让人感到很烦躁。因此,CI-CD(持续集成和持续交付)工作流应运而生。
CI-CD 工作流或流水线使我们能够在相对较短的时间内(通常只需几分钟)安全地构建、测试和部署 Web 应用程序。那么 Django 呢?如果您在 GitHub 上托管了一个 Python 应用程序代码库,那么在更新代码库后立即将其推送到托管环境将非常方便。这正是我们将使用 GitHub Actions 来实现的,该工具自 2019 年底起免费向公众开放。
让我们开始吧!
1. AWS Beanstalk 环境
在开始配置一切之前,我们需要确保我们的环境已经准备就绪。
如果您已有 AWS 账户,请前往控制台并搜索“Beanstalk”。如果没有,请在此处创建一个。系统将要求您添加账单信息才能继续。
在 Beanstalk 仪表板中,请确保在右上角选择了最合适的区域(要部署服务的区域)。勾选 [环境] 并选择 [创建新环境]。然后在弹出的对话框中,选择 [Web 服务器环境]。
填写详细信息并关注平台部分。在这里我们需要选择 Python 平台(最新版本)和最新可用的 Amazon Linux 2。
退出示例应用程序并点击[创建环境]。片刻之后,您应该能够打开环境 URL 地址并查看示例页面。
打开环境页面,复制左上角显示的应用程序名称和环境。
这里要做的最后一件事是设置 Django 的数据库。
进入[配置] → [数据库]并选择首选选项:
在这个例子中,我选择了 PostgreSQL,因为这是我通常的选择,但如果您愿意,您可以坚持使用 MySQL 甚至 Oracle。
警告: 以这种方式创建的数据库服务器仅适用于测试目的。它将严格连接到环境。如果您删除或重新创建 Beanstalk 环境,数据库将被删除。在生产环境中,您应该使用VPC内的独立 RDS 或 Aurora 服务器。
现在我们已经有了托管的 Python 环境和数据库,我们需要为未来的应用程序构建准备一个文件存储。
2. S3 配置
在将构建推送到 Beanstalk 之前,我们需要设置一个自定义 S3 存储桶作为构建的临时存储。
在 AWS 控制台中搜索 S3 或从菜单中切换到它。然后选择[创建存储桶]。输入一个唯一的名称,并选择你的区域。
保留“阻止所有公共访问”复选框并继续[应用]。
接下来我们需要做的是生成编程访问凭证,GitHub Action 将使用它来部署我们的 Django 应用程序。
3. IAM 用户访问 🔐
在 AWS 控制台中搜索 IAM 用户,并选择[添加用户]。
在权限页面,选择 [直接附加现有策略]。搜索 S3FullAccess* 并选中复选框。对AdministratorAccess-AWSElasticBeanstalk * 重复相同步骤,然后点击[添加用户]。
最后,复制上一步中的访问密钥 ID 和密钥。请确保将此信息保存在安全的地方,因为用户密钥只会显示一次。
看起来我们已经完成了 AWS 并准备继续使用 GitHub!
4. GitHub 工作流程设置
返回你的 Django 项目并创建一个名为 的文件夹.github
。并在其中创建一个名为 workflows 的文件夹。GitHub Actions 配置应放置在其中,并使用 YAML 语法进行格式化。请参阅下面的示例:
#Location: .github/workflows/custom_config.yml
name: CI-CD pipeline to AWS
env:
EB_S3_BUCKET_NAME: "YOUR BUCKET NAME FROM Step 2"
EB_APPLICATION_NAME: "YOUR APP NAME FROM Step 1"
EB_ENVIRONMENT_NAME: "YOUR ENVIRONMENT NAME FROM Step 1"
DEPLOY_PACKAGE_NAME: "django-app-${{ github.sha }}.zip"
AWS_REGION_NAME: "YOUR AWS REGION ("us-east-1"/"eu-central-1" etc.)"
on:
push:
branches:
- master #Use your own branch here (Might be staging or testing)
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Git clone on our repo
uses: actions/checkout@v2
- name: Create zip deployment package
run: zip -r ${{ env.DEPLOY_PACKAGE_NAME }} ./ -x *.git*
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.aws_access_key_id }}
aws-secret-access-key: ${{ secrets.aws_secret_access_key }}
aws-region: ${{ env.AWS_REGION_NAME }}
- name: Copying file to S3
run: aws s3 cp ${{ env.DEPLOY_PACKAGE_NAME }} s3://${{ env.EB_S3_BUCKET_NAME }}/
- name: Print nice message on success finish
run: echo "CI part finished successfuly"
deploy:
runs-on: ubuntu-latest
needs: [build]
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.aws_access_key_id }}
aws-secret-access-key: ${{ secrets.aws_secret_access_key }}
aws-region: ${{ env.AWS_REGION_NAME }}
- name: Create new EBL app ver
run: |
aws elasticbeanstalk create-application-version \
--application-name ${{ env.EB_APPLICATION_NAME }} \
--source-bundle S3Bucket="${{ env.EB_S3_BUCKET_NAME }}",S3Key="${{ env.DEPLOY_PACKAGE_NAME }}" \
--version-label "${{ github.sha }}"
- name: Deploy new app
run: aws elasticbeanstalk update-environment --environment-name ${{ env.EB_ENVIRONMENT_NAME }} --version-label "${{ github.sha }}"
- name: Print nice message on success finish
run: echo "CD part finished successfuly"
让我们深入了解一下配置块并检查它们的用途。更多详情请见此处。
1) [env]块作为配置中变量的快捷方式列表。我们在这里定义非敏感数据。
2)[jobs]块定义了实际要做的事情。
3) [build]块只是一个作业名称,其中包含构建过程中要执行的一系列“步骤”。对于纯 Django 应用来说,这仅意味着压缩工作目录并将其推送到 S3 存储桶。
4)[步骤]块列出了要在虚拟机上执行的名称和实际命令。
您可以轻松添加另一个名为测试的作业名称并在其中运行./manage.py 测试步骤。
5) [needs]块是进一步执行的先决条件。在我们的例子中,我们要确保在向 Beanstalk 发送命令之前,文件传输已成功完成。
6)[on]块指定触发事件,比如我们的“推送”,以及目标分支。
如果您有多个 Beanstalk 环境(QA、测试、登台、生产等),您需要为它们放置新的 config.yml 文件并相应地更改环境变量和分支。
您可能还注意到我们还没有定义secrets.aws_access_key_id
或secrets.aws_secret_access_key
。🧊 让我们解决这个问题!
打开你的 GitHub 仓库或为你的项目创建一个,然后前往[设置] → [密钥] → [新仓库密钥]。像这样粘贴你的 IAM 用户密钥和密钥:
重复同样的步骤,修改aws_secret_access_key and
它的值。就这样!
5. 准备 Django 设置
还记得吗,我们在步骤 1 中将关系数据库连接到了 Beanstalk 环境?但是连接参数和数据库用户凭据在哪里呢?
通过集成数据库,Beanstalk 公开了可以立即使用的环境变量:
# main_django_app settings.py
import os
ALLOWED_HOSTS = ['YOUR_ENVIRONMENT_HOST']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': os.environ['RDS_DB_NAME'],
'USER': os.environ['RDS_USERNAME'],
'PASSWORD': os.environ['RDS_PASSWORD'],
'HOST': os.environ['RDS_HOSTNAME'],
'PORT': os.environ['RDS_PORT'],
}
}
# rest of the settings
不要忘记将您的环境 URL 和主域添加到允许的主机列表中。
此时,我们需要确保 Beanstalk Python 平台已准备好与 PostgreSQL 建立连接。让我们告诉它为我们安装一些附加组件。
在项目根目录中创建一个名为的文件夹.ebextensions
并在其中放置一个文件01_packages.config
:
packages:
yum:
amazon-linux-extras: []
commands:
01_postgres_activate:
command: sudo amazon-linux-extras enable postgresql10
02_postgres_install:
command: sudo yum install -y postgresql-devel
现在我们需要添加 Django 配置,以便将我们的主应用程序和设置告知 Beanstalk 的 WSGI 服务器。在.ebextensions
文件夹中创建另一个名为的文件django.config
:
option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: main_django_app.wsgi:application
aws:elasticbeanstalk:application:environment:
DJANGO_SETTINGS_MODULE: main_django_app.settings
"PYTHONPATH": "/var/app/current:$PYTHONPATH"
aws:elasticbeanstalk:environment:proxy:staticfiles:
/static: static
将main_django_app更改为您的 Django 应用程序名称。
最后一行aws:elasticbeanstalk:environment:proxy:staticfiles0:
告诉通过反向代理提供哪个文件夹以及使用哪个相对 URL。
最后,使用冻结您的本地 python 环境pip freeze > requirements.txt
(它将成为 Beanstalk 配置 EC2 环境的主要来源)。
6. 首次运行🔥
将所有更改推送到您指定的分支,然后访问“操作”选项卡。如果操作成功完成,您将看到绿色标记。如果出现问题,请打开日志并解决其中的错误。
GitHub Actions 成功运行后出现错误?请访问 Elastic Beanstalk 环境并检查日志。
希望您能看到类似这样的内容:
7. 编写部署后命令(钩子)🔌
部署后仍有几个命令需要执行。
1)我们需要将我们的更改迁移到 Beanstalk 数据库(makemigrations 命令创建的迁移文件应该是代码库的一部分)。
2)我们需要收集静态文件(不需要将静态文件保存在代码库中)。
这个问题可以通过 Beanstalk 的部署后钩子解决。文件名可以完全自定义,但文件扩展名很重要。所有 .sh 文件都将按字母数字顺序执行。
在项目根目录中,创建.platform
具有以下结构的文件夹:
.platform/
└───hooks/
└───postdeploy/
-01_django.sh
#!/bin/bash
source /var/app/venv/*/bin/activate && {
# collecting static files
python manage.py collectstatic --noinput;
# log which migrations have already been applied
python manage.py showmigrations;
# migrate the rest
python manage.py migrate --noinput;
# another command to create a superuser (write your own)
}
你已经明白了!现在,你可以了解如何创建超级用户帐户了。
⚠️重要提示:
–查看 IAM 用户访问策略。出于教程目的,我已授予 S3 和 Beanstalk 的完全访问权限。请确保仅授予 GitHub Actions 客户端所需的权限,以防止密钥泄露造成不良后果。
–为 S3 存储桶和应用程序版本存储添加生命周期规则。默认情况下,S3 不会从存储桶中删除应用程序版本或任何其他文件。在 S3 和 Beanstalk 中使用生命周期规则,可以仅保留所需的应用程序版本。
由于 Django 标头中的 ALLOWED_HOSTS 限制,AWS Beanstalk 健康检查系统可能无法正常工作(严重健康状态)。我不知道该如何正确处理这个问题(您可以忽略状态警告,或者ALLOWED_HOSTS = ['*']
自行承担风险)。
– 如果您要使用 PostgreSQL,请不要忘记安装软件包pip install psycopg2-binary
并冻结 requirements.txt。
有用的链接:
如何为不同的环境拆分 Django 设置
如何在 AL2 Beanstalk 上使用 Supervisor 配置 Django Q
将 Django 应用程序部署到 Elastic Beanstalk
GitHub Actions 的工作流语法
希望你喜欢本指南。敬请期待,下次我可能会介绍如何搭建一个基于 Django 的全栈项目,并带来真正无缝的开发体验。
本文最初发表在我的博客文章中。
文章来源:https://dev.to/vlntsolo/django-full-ci-cd-flow-to-aws-with-github-actions-and-s3-2enp