如何使用 Terraform 和 Ansible 将应用程序部署到 AWS EC2 实例。
我最近有机会研究这个问题,在成功完成设置之前,我不得不结合不同的教程和文章。
因此,我写这篇文章是希望它能让一些人的工作更轻松,也能让想要学习这方面的初学者更清楚地了解相关知识。
什么是基础设施即代码?
基础设施即代码 (IaC) 是通过机器可读文件来设置和管理云基础设施的过程,而不是手动设置所需的基础设施。
文件写入完成后,您可以使用基础设施即代码 (IaC) 工具运行它们来构建和配置云基础设施。毋庸置疑,这比手动设置要便捷得多。
IaC 工具包括:Terraform、Ansible、Chef、AWS CloudFormation、Puppet、Vagrant 等。
基础设施即代码的优势
- 使用 IaC,基础设施配置和设置速度要快得多:您只需运行一个脚本即可。
- 脚本可以随时轻松重复使用。
- 此外,在不同的但相似的设置之间进行细微的修改也更容易。
- 它能提高网站可靠性。
- 它降低了基础设施搭建过程中出错的可能性。
在本教程中,您将学习如何使用 Terraform 为 React 应用程序配置服务器(AWS EC2),然后使用 Ansible 配置必要的软件包。
我们先列出所有必要步骤,然后在下文中详细解释:
我的文件夹结构
先决条件
如果您想按照本教程进行操作,请确保在操作前满足以下要求。
- AWS账户。如果您还没有账户,可以在这里创建一个,并按照本教程进行设置。
- AWS CLI和AWS Vault。
- Docker和Dockerhub帐户。
- Terraform
- Ansible
- 一个 React 应用示例。你可以参考这篇教程创建一个。
现在,让我们开始吧!
步骤 1 — 配置 AWS CLI 和 AWS Vault
我们需要在 AWS 账户上创建一个用户才能配置 AWS CLI。
为此,请登录您的 AWS 账户,转到“服务”,然后单击“IAM”。单击“用户”,然后单击“添加用户”。输入用户名,然后选择“程序化访问”作为 AWS 访问类型。
接下来,我们需要为用户创建一个组。点击“创建组”并赋予其管理员权限。您可以添加标签(可选),点击“下一步”查看用户详细信息,然后点击“创建用户”。
之后,将显示一个新屏幕,用于下载用户安全凭据。点击Download.csv。
现在,回到终端并运行以下命令:
aws configure
按照提示添加用户访问密钥 ID和秘密访问密钥。然后输入您首选的AWS 区域和输出。
运行以下命令,并确保将 替换username为之前从 AWS 控制台创建的用户。
aws-vault add <username>
按照提示添加用户访问密钥 ID和秘密访问密钥。这样做是为了将您的 AWS 凭证存储在您计算机的本地密钥库中。
然后运行以下命令以验证您的身份并建立会话。
aws-vault exec <username>
步骤 2 — 为服务器创建密钥对
我们需要密钥对才能运行我们的实例。
要创建密钥对,请转到您的 AWS 控制台,从“服务”下拉菜单中选择EC2 ,单击“密钥对”,然后单击“创建密钥对”按钮。
输入密钥名称,选择pem(适用于 openSSH)或ppk(适用于 PuTTY),然后单击“创建密钥对”。
下载密钥并将其移动到您计算机上的.ssh文件夹。对于 Ubuntu 和 macOS,该文件夹很可能位于~/.ssh。
步骤 3 — 将应用程序 Docker 化
在react-app文件夹的根目录下,创建一个Dockerfile 文件,并添加以下几行:
FROM node:12.18.3
LABEL version="1.0"
LABEL description="This is the base docker image for my React app"
LABEL maintainer="abc@mail.com"
WORKDIR /usr/src/app
COPY ["package.json", "yarn.lock", "./"]
RUN yarn
COPY . .
EXPOSE 3000
CMD ["yarn", "start"]
以下是命令概述:
FROM定义了容器使用的镜像。在本例中,我们使用的是 node:12.18.3。LABEL
指示Dockerfile 的版本、描述和维护者。WORKDIR设置应用程序的工作目录,如果目录不存在则创建它。COPY用于将文件从一个目标位置复制到另一个目标
位置。最后一个路径始终是文件复制到的目标位置。RUN定义了 Docker 要运行的命令。我在这里使用了 yarn,因为我使用 yarn 安装了 React 应用程序,如果 npm 更合适,您可以将其更改为 npm。EXPOSE告诉 Docker 在运行容器时应该监听哪个端口。CMD定义了启动容器的命令。我使用了我的 React 应用程序启动脚本中指定的 yarn start,您应该确保您的命令也与您的应用程序启动脚本中的命令一致。
现在,你需要根据 Dockerfile 构建 Docker 镜像。为此,请在react-app文件夹的根目录下运行以下命令:
docker build -t <image-name> .
请务必将替换image-name为应用程序的图像名称。
现在,运行以下命令,从镜像启动一个容器。
docker run -it -p 3000:3000 <image-name>
请在浏览器中访问http://localhost:3000查看该应用。
返回终端,使用以下命令为图像添加标签:
docker tag <image-name> <docker_hub_username>/<repo-name>:<tag-name>
请务必将所有变量替换为适当的值。
接下来,使用以下命令从终端登录您的 DockerHub 帐户:
Docker login
根据提示输入您的用户名和密码。
然后运行以下命令将镜像推送到 Dockerhub。
docker push <docker_hub_username>/<repo-name>:<tag-name>
完成后,您应该能在创建的仓库中看到您的 Docker 镜像。
步骤 4 — 使用 Terraform 配置服务器
在项目文件夹的根目录下,创建一个名为terraform 的文件夹。在 terraform 文件夹内,创建一个名为frontend 的新文件夹。我们将把前端的所有配置文件都放在这里。接下来,在 frontend 文件夹内创建一个名为main.tf的文件。
将以下代码放入main.tf文件中。
provider "aws" {
region = "us-east-1"
}
variable "name" {
description = "Name the instance on deploy"
}
resource "aws_instance" "admin_frontend" {
ami = "ami-042e8287309f5df03"
instance_type = "t2.micro"
key_name = "admin"
tags = {
Name = var.name
}
}
这里,我们使用 Ubuntu 服务器镜像(ami-042e8287309f5df03)创建一个 AWS EC2 实例,实例类型为t2.micro ,密钥对名称为admin(我们之前创建的密钥对名称)。请确保将region、ami、instance_type和key.name替换为您实际配置中的值。
在终端中,cd进入前端文件夹,运行以下命令来初始化包含 Terraform 配置文件的工作目录。
terraform init
之后,运行以下命令来验证是否已正确设置。
terraform plan
稍后会提示输入值,请输入实例名称frontend。
接下来,运行以下命令来启动您的 EC2 实例。
terraform apply
这也会提示输入值,frontend再次输入实例名称,然后在下一个提示中按 Enter 键yes确认。
现在,如果您在 AWS 控制台上查看正在运行的实例,应该就能看到它了。
步骤 5 — 为服务器创建安全组
现在我们需要为前端实例创建一个安全组。
前往 AWS 控制台,从“服务”下拉菜单中选择EC2,然后单击“安全组”。单击“创建安全组”,然后添加安全组名称和描述。
向下滚动到“入站规则”,然后单击“添加规则”。选择“HTTP”作为类型, “任意位置”作为源。完成后,再创建一条入站规则,将类型设置为“所有 TCP”,源设置为“任意位置”。最后,创建一条入站规则,将类型设置为“SSH”,源设置为“我的 IP”。这样就总共创建了三条入站规则。
将出站规则的“类型”保留为“所有流量” ,“目标”保留为0.0.0.0/0。然后单击“创建安全组” 。如果您想了解更多关于安全组的信息,可以阅读这篇文章。
现在,返回前端实例并将创建的安全组附加到该实例。为此,请选择前端实例,然后选择“操作” > “安全” > “更改安全组” >单击搜索字段并选择安全组,删除默认安全组,然后保存。
现在,您可以使用以下命令尝试通过 SSH 连接到您的服务器:
ssh -i "~/.ssh/<your_KeyPair>.pem" <ec2-user>@<public_IPv4_DNS>
请务必将ec2-userAMI 用户名替换public_IPv4_DNS为实例公共域名,并将密钥文件名替换your_KeyPair为密钥文件名称。
步骤 6 — 使用 Ansible 配置服务器
现在我们的实例已经运行起来了,我们需要使用 Ansible 安装必要的软件包。在此之前,让我们先向 Ansible 配置文件添加一些设置。
打开终端并运行以下命令来打开配置文件。我用的是vim 编辑器,但你可以随意选择任何你喜欢的编辑器。
sudo vim /home/<username>/.ansible.cfg
请务必将此处的用户名替换username为您自己的用户名。
然后插入以下内容,确保将 替换your_KeyPair为您的密钥名称。
[defaults]
host_key_checking = False
private_key_file=~/.ssh/<your_KeyPair>.pem
inventory=/etc/ansible/hosts
remote_user = ubuntu
[ssh_connection]
control_path=%(directory)s/%%h-%%r
control_path_dir=~/.ansible/cp
#pipelining = True
scp_if_ssh = True
现在保存并退出。
我们还需要将主机添加到 Ansible 的 hosts 文件中。为此,请运行以下命令打开 Ansible hosts 文件:
sudo vim /etc/ansible/hosts
然后将这些行添加到文件中。请确保将 ` ec2-user<AMI 用户名>` 替换为 AMI 用户名,public_IPv4_DNS将 `<实例公共域名>` 替换为实例公共域名,并将`<your_KeyPair密钥名称>` 替换为您的密钥名称。
[frontend] ec2-user@public_IPv4_DNS ansible_ssh_private_key_file=~/.ssh/your_KeyPair.pem
保存并退出。
现在,请使用以下命令 ping 通您的受管节点,确保可以访问到它:
sudo ansible all -m ping
如果无法访问,则可能是网络连接问题,需要进行一些调试。但是,如果您收到绿色 JSON 数据块,则一切正常。
现在,进入项目根目录,创建一个名为ansible 的文件夹。在该ansible文件夹内,创建一个名为provision_frontend.yaml 的文件。
将以下几行添加到provision_frontend.yaml 文件中
---
- hosts: frontend
become: yes
become_method: sudo
tasks:
- name: Install pip
apt:
update_cache: yes
name: python3-pip
- name: Install aptitude using apt
apt: name=aptitude state=latest update_cache=yes force_apt_get=yes
- name: Install required system packages
apt: name={{ item }} state=latest update_cache=yes
loop: [ 'apt-transport-https', 'ca-certificates', 'curl', 'software-properties-common', 'python3-pip', 'virtualenv', 'python3-setuptools']
- name: Add Docker GPG apt Key
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Add Docker Repository
apt_repository:
repo: deb https://download.docker.com/linux/ubuntu bionic stable
state: present
- name: Update apt and install docker-ce
apt: update_cache=yes name=docker-ce state=latest
- name: install docker-py
pip: name=docker-py
- name: enable Docker services
service:
name: "docker"
state: started
enabled: yes
- name: Check if container is running
shell: docker ps
- name: run docker image
shell: docker run -dit --name <repo-name> -p 3000:3000 <docker_hub_username>/<repo-name>:<tag-name>
- name: show running images
shell: docker images
请务必编辑运行 docker 镜像的 shell 命令,使其与您的设置相匹配。
然后保存。
hosts定义了 playbook 中命令执行的目标主机。become_method设置为 root 用户。package用于安装软件包。service用于控制远程主机上的服务。shell用于
运行命令。
在终端中,导航到ansible文件夹,然后使用以下命令运行 playbook:
ansible-playbook provision_frontend.yaml
现在,打开浏览器,输入实例的公共地址,并在末尾加上3000 。
耶!就是这样!虽然内容可能有点多,但我希望它能对你的旅程有所帮助。
如果您想使用Jenkins为您的应用程序设置 CI/CD ,您可以查看我的另一篇文章(链接在此)。
如果您觉得这篇文章对您有帮助,请点赞或留言。如果您有任何问题或建设性意见,请在评论区留言。
也别忘了关注我,获取更多文章。谢谢!
















