使用Packer进行配置和变更管理,并可以将部署到AWS。

在本文中,我们将研究Ansible和Packer,以及如何使用这些工具来自动执行配置状态(即配置和变更管理)的应用程序。
DevOps的核心是配置 。 通过配置,我们能够组织和链接用于DevOps工作的所有资源,但实际上是什么呢?

可以将配置管理(CM)定义为系统地处理系统更改的过程,以使其随时间保持该系统中资产之间的一致性。 它的目的是识别和跟踪各个配置项,记录其功能能力及其相互依赖性,并弄清楚如何最好地利用它们。

变更和配置管理是互补的。 变更管理的主要目标是控制并确保仅允许对配置项进行授权的变更,以减轻新变更导致的风险和对资源的影响。 使用工具,我们能够自动执行许多流程,从而节省了大量时间,并大大减少了人为错误的机会,原因是工程师与系统之间的直接互动减少了。

将变更管理集成到您的流程中涉及以下步骤:

  • 所有更改都必须通过单一途径批准 。 这样可以确保在通过途径进行更改之前,您可以考虑进行了哪些其他更改以及它们如何与新更改关联,以及这些更改可能对整个生态系统产生什么影响。
  • 作为团队,开发人员和运营工程师, 彼此之间的工作必须具有一定的透明度 。 如果一只手臂不知道另一只手臂在做什么,但是他们正在同一个项目上工作,那么它们必然会发生冲突。 知道每个团队正在使用什么,可以使他们达到共同/工作的基础。
  • 根据所需的资源,紧急程度,对生态系统的影响等,对组织进行的所有可能更改进行分类 。 这使您可以系统地计划如何实现它们。
  • 您必须提出有关如何处理更改的策略和策略 。 这为整个过程提供了结构,并最大程度地减少了错误余地。
  • 建立了以上所有功能后,将使用各种配置工具(例如Terraform,AWS云形成和Packer)以及配置管理工具(例如Chef,Puppet,SaltStack和Ansible)来实现这些更改。 当我使用Packer和Ansible部署Python / Flask API时,我们将对其进行更多研究。

在为您的公司确定配置管理系统时,必须考虑一些事项。

  • 配置管理计划 :必须对配置管理进行计划,以使其有效,可预测和可重复。 该计划应详细说明任何特定步骤及其在生命周期中的应用范围。 它还应确定执行配置管理的角色和职责。
  • 配置标识 :将工作分解为较小的可管理任务(配置项),创建唯一的编号或参考系统,并建立配置基线;
  • 配置控制 :这样可确保记录对配置项的所有更改。 这使您可以弄清楚如何连接配置项。
  • 配置状态统计 :保留记录可让您知道配置的当前状态,并能够在配置项目的开发和操作过程中对其进行跟踪
  • 配置验证和审核:一种确认所配置是否符合其预期要达到的要求的方法。

配置管理的好处

  • 通过配置管理,您可以极大地提高组织的能力,以识别需要修改哪些内容以完成更改以及更改的后果。
  • 通过使用工具和已建立的结构,可以在发生故障时更快地进行恢复。
  • 通过更快地交付解决方案,改进和恢复,可以改善服务交付并提高客户满意度。
  • 由于更好地了解当前IT服务模型的总成本,因此可能会降低运营成本。
  • 更改授权过程提高了安全性,因此可以轻松识别可能增加安全漏洞的更改,还可以轻松检测到未经授权的更改。
  • 由于跟踪所有变更,因此更容易观察变更的结果,从而有效地做出更明智的业务决策。

选择配置管理工具

为您的团队和组织选择最佳的工具集对于成功采用配置管理系统至关重要。 市场上有许多工具,每种工具具有不同的功能集和不同的复杂程度。 选择工具时,需要考虑以下因素:

  • 您的需求
    重要的是,要全面了解要使用工具解决的问题,以便您搜索的方式不仅是任何CM工具,而且是解决问题的工具。
  • 包容性
    这些工具应具有包容性,可以使您的团队之间进行全面协作,并在需要时允许他们使用自己的工具。
  • 基础架构复杂度
    根据项目或组织的规模,基础结构复杂性的级别会有所不同,但是,重要的是要考虑到可伸缩性和安全性等方面,而这些可能无法由工具强制实施。
  • 学习曲线
    您的团队适应这些工具的速度将取决于基础架构要求以及工具自定义语法。 看到投资回报需要多长时间最终取决于团队适应工具所需的时间。
  • 成本
    您只能获得负担得起的东西。 费用,包括订阅费用,培训团队所花费的时间或雇用已经具备必要知识和技能的人员的成本。

Packer和Ansible在一起

如前所述,我们将使用Packer作为供应商,并使用Ansible进行配置管理,以将Python / Flask API部署到AWS上以创建Amazon Machine Image(AMI)。

Packer和其他预配软件使您可以更轻松地确保从开发到生产都运行相同的软件,而不必担心会潜行更改。

首先,在您的计算机上安装Packer和Ansible。 我使用Homebrew将其安装在Macbook上,具体取决于您使用的操作系统,执行此操作的方法可能有所不同。
运行以下命令进行安装:
brew install ansible
brew install packer

接下来,我们将创建打包程序模板。

Packer模板—这是一个json文件,通过配置Packer的各种组件来定义一个或多个构建。 Packer读取模板,并使用这些设置并行创建多个机器映像。 在我们的情况下,我们将仅配置一个映像,因此我们将看不到在Paralle中创建的实现。 也许我会回到本文,并在没有时间的情况下将其包括在内。

模板

  { 
“变量”:{
“ access_key”:“ {{env`aws_access_key`}}”,
“ secret_key”:“ {{env`aws_secret_key`}}”,
“ ami_id”:“ {{env`ami_id`}}”,
“ region”:“ {{env`region`}}”
},
“建筑商”:[
{
“ type”:“ amazon-ebs”,
“ region”:“ {{user`region`}}”
“ access_key”:“ {{user`access_key`}}”,
“ secret_key”:“ {{user`secret_key`}}”,
“ source_ami”:“ {{user`ami_id`}}”,
“ instance_type”:“ t2.micro”,
“ ssh_username”:“ ubuntu”,
“ ami_name”:“ cp3-17-{{isotime | clean_ami_name}}”,
“ ami_description”:“带有Ubuntu 16.04实例的CP3 ansible打包程序AMI”,
“标签”:{
“角色”:“ python-api-17-12-17”
},
“ run_tags”:{
“角色”:“ buildSystem”
}
}
],
“供应商”:[
{
“ type”:“ ansible”,
“ playbook_file”:“ ./pacsible-playbook.yml”
}
]
}

variables 在此处定义自定义用户变量,在本例中为ami_id,区域和Amazon Web Services(AWS)访问密钥和秘密密钥。 可以在IAM用户安全证书下的AWS上找到AWS密钥 将它们添加到您的环境变量中,它们将被打包程序拾取。 ami_idsource_ami的ID,而region是应在其中创建实例的区域。 使用var参数运行构建时,这些将被传递到模板。
NOTE: Do not explicitly add your AWS credentials in the packer file if you plan to share it anywhere. These credentials can be used to spin up images on your account as you will soon see so sharing them publicly is a recipe for disaster.

builders: 这将控制Packer所基于的基本系统,并按照本节中的设置来创建计算机映像。
在我们的构建器中,我们有:

  • 告诉打包程序创建由EBS卷支持的Amazon AMI的type ,以便在EC2中使用。
  • region启动EC2实例创建AMI的区域名称。
  • 变量部分中前面提到的用于与AWS通信的access keysecret key
  • source_ami是一个预先存在的图像,用作我们将要创建的图像的基础。
  • instance_type是构建AMI时要使用的EC2实例类型。
  • ami_name是用于标识映像的名称。 我们使用isotime变量获取创建图像时的时间,并将其附加到名称中以确保名称唯一,并使用clean_ami_name变量从名称中删除时间中不允许的任何字符。
  • 应用于AMI的tags
  • run_tags应用于启动以创建映像的实例,以便于识别。

provisioners : 在本节中,您可以拥有一个由所有组件组成的阵列,这些组件可以在运行的计算机中安装和配置软件,然后将其转变为静态映像。 他们确保映像具有所有必需的软件。 在我们的预配器部分,我们只有一个。
每个供应商定义均采用json对象的形式,其中包含用于配置供应商的密钥。 type键是预期的,它指定要使用的供应者的名称,在我们的示例中,这是Ansible。 playbook_file告诉打包程序哪个文件将由Ansible执行。

Ansible剧本
Ansible剧本是YAML文件。

  --- 
-主持人:全部
成为:是的
  vars: 
ansible_python_解释器:“ / usr / bin / python3”

角色:
- 设定
-应用
- 网络服务器
-服务
-开始

顶部的3个连字符是yaml语法,用于指示文档的开始。

hosts: all 告诉ansible收集清单中所有主机的事实。
become —这是启用特权升级的标志。 它允许您“成为”另一个用户,该用户不同于登录到计算机的用户(远程用户)。 默认的特权升级用户是root

vars这是指变量。 这就是如何处理不同系统之间的差异。
ansible_python_interpreter —这将ansible_python_interpreter指向本地计算机上的python可执行文件,应将其用于调用ansible命令行工具。
roles -角色是一种基于已知文件结构自动加载某些vars_files,任务和处理程序的方法。
在我们的配置中,我们具有五个角色,即setupappwebserverservicestart。 角色必须按照执行顺序列出。

的角色

为了使角色正常工作,您必须遵循特定的目录结构,并且他们希望文件位于某些目录名称中。

 角色 
|-角色的文件夹名称
|-目录内容名称
| --- main.yml
playbook.yml

在上面的结构中,我们有角色文件夹,在角色文件夹中有一个以角色名称命名的文件夹,这由您自己决定,但是理想情况下,它应该描述角色正在实现的内容,并且应该是您的名字在playbook yaml文件的角色部分下添加。 在该文件夹中,您有以内容命名的文件夹。 这仅限于一组可预定义的目录名称,其中包括任务,处理程序,默认值,vars,文件,模板元数据。 对于此实现,我们将仅处理任务。 任务是此角色要执行的任务的主要列表。 您可以从有关角色的ansible文档中阅读其余内容。

角色细分

设定

该角色将应用程序先决条件添加到映像中

  --- 
-名称:添加python 3.6信息库
apt_repository:
回购:ppa:deadsnakes / ppa
状态:存在
  -名称:安装python 3.6 
易于:
名称:python3.6
update_cache:是
  -名称:安装python3-pip nginx python3.6-gdbm 
易于:
名称:“ {{item}}”
状态:存在
with_items:
-python3-pip
-Nginx
-python3.6-gdbm

name -这是对块的描述,并在运行该块时显示在日志中。
apt_repository —这指示apt_repository在OS软件包中添加或删除存储库。 它特定于Ubuntu或Debain系统。 在实现中,我们添加了python3.6存储库。
repo —这是一个git参数,指向要克隆的存储库
state -告诉ansible将源设置为最新状态。
apt —用于管理apt软件包。 在这里它用于安装几个软件包。
update_cache —这等效于apt-get update命令,该命令从存储库下载软件包列表并对其进行“更新”,以获取有关软件包的最新版本及其依赖项的信息。
with_items —使用itemwith_items实现apt是安装多个软件包的一种方式。 这是一个将重复任务作为一个整体处理的标准循环。

应用程式

该角色负责将项目目录添加到映像并进行设置

  -名称:创建项目目录 
文件:
路径:/ var / www / project
状态:目录
  -名称:克隆应用程序存储库 
git:
回购:https://github.com/Thegaijin/RecipeAPI.git
目标:/ var / www / project / RecipeAPI
版本:api_defence
  -名称:安装virtualenv 
命令:pip3 install virtualenv
  -名称:创建virtualenv 
命令:virtualenv / var / www / project / env -p python3.6
created =“ / var / www / project / env”
  -名称:安装项目要求 
点:
要求:/var/www/project/RecipeAPI/requirements.txt
virtualenv:/ var / www / project / env
  -名称:创建.env文件 
贝壳:
chdir:/ var / www / project /
创建:\ .env
cmd:|
sudo bash -c'cat> \ .env << EOF
出口SECRET_KEY ='wqrtaeysurid6lr7'
export FLASK_CONFIG =开发
导出DATABASE_URL ='postgresql:// thegaijin:12345678@cp3-db-instance.cjfdylbgjjyu.us-west-2.rds.amazonaws.com:5432 / recipe_db'
EOF'

file -设置文件,符号链接和目录的属性,或删除文件/符号链接/目录。 在我们的例子中,我们正在创建目录,以便它设置目录的属性。
path —告诉ansible名称和创建目录的位置
state —告诉ansible应该创建目录。 当像我们这样的目录时,如果所有中间子目录都不存在,则将创建它们。
git —您可能已经猜到了,ansible是如何管理存储库的git检出以部署文件或软件的。
dest —这也是一个git参数,它指向您要将存储库克隆到的目录
version -这是另一个git参数,用于声明您要检出的分支。
command-从远程节点运行命令。 在此实现中,我将使用pip3安装virtualenv。
creates -这是一个告诉命令创建文件或目录的参数。
pip —管理python依赖项。 在此实现中,我将使用它在我的需求文件中安装依赖项。
Requirements( requirements —该参数告诉pip在哪里可以找到依赖项列表,这是requirements.txt文件。
virtualenv —该参数为pip提供了要安装到的virtualenv目录的路径。
shell这与使用命令相似,不同之处在于它通过远程节点中的shell运行命令。
chdir此参数将目录更改为指定目录。
cmd —此参数后面是要在Shell中执行的命令。 如果有多个命令,则使用竖线字符。 在此实现中,使用它来创建带有环境变量的.env文件。

网络服务器

该角色负责nginx的配置,该配置用作应用程序反向代理。

  --- 
-名称:在启动时启动Nginx
服务:
名称:nginx
启用:是
状态:开始
  -名称:删除nginx default.conf 
命令:rm -rf / etc / nginx / sites-available / default / etc / nginx / sites-enabled / default
  -名称:添加Nginx配置 
贝壳:
chdir:/ etc / nginx / sites-available /
创建:默认
cmd:|
sudo bash -c'cat>默认<< EOF
服务器{
听80;
地点 / {
proxy_pass http://127.0.0.1:8000/;
proxy_set_header主机\ $ host;
proxy_set_header X-Forwarded-Proto \ $ scheme;
proxy_set_header X-Real-IP \ $ remote_addr;
proxy_set_header X-Forwarded-For \ $ proxy_add_x_forwarded_for;
}
}
EOF'
  -名称:创建符号链接 
命令:ln -s / etc / nginx / sites-available / default / etc / nginx / sites-enabled /
  -名称:重新加载nginx 
命令:systemctl重新启动nginx

service -用于控制远程主机上的服务。 在这种情况下,服务为nginx。
enabled —这是一个服务参数,用于将服务设置为在启动时启动
statestate —一个具有多个选择的服务参数,这些参数将根据需要实现提供给它的选择,例如,在这种情况下,该选择已启动,如果nginx未运行,它将触发服务启动它。

我以这个角色启动nginx,删除默认配置文件,使用bash通过shell创建新的配置文件,在启用了站点的nginx文件夹中为新配置创建符号链接,最后重新加载nginx以加载新配置。

服务

该角色创建一个systemd服务来启动应用程序并保持其运行。

  --- 
-名称:创建启动脚本
贝壳:
chdir:/ var / www / project / RecipeAPI /
创建:startenv.sh
cmd:|
cat> startenv.sh << EOF
#!/ bin / bash

cd / var / www / project /

源环境/ bin /激活
源.env
  cd RecipeAPI 

gunicorn manage:app
紧急行动
  -名称:创建启动服务 
贝壳:
chdir:/ etc / systemd / system /
创建:recipe.service
cmd:|
猫>配方服务<< EOF
[单元]
描述=配方启动服务
之后= network.target
  [服务] 
用户= ubuntu
ExecStart = / bin / bash /var/www/project/RecipeAPI/startenv.sh
重启=总是
  [安装] 
WantedBy =多用户目标
紧急行动
  -名称:更改文件权限 
外壳:|
须藤chmod 744 /var/www/project/RecipeAPI/startenv.sh
须藤chmod 664 /etc/systemd/system/recipe.service

我在这里使用bash在外壳中创建了一个名为startenv.sh的启动脚本,还创建了名为startenv.sh的系统服务,该服务传递了启动脚本并更改了文件权限,从而赋予了脚本读取,写入和执行权限以及服务读取权限并读取权限。

开始

起始角色是难题的最后一部分。 它会重新加载所有systemd守护程序以获取任何配置更改,使recipe.service在引导时启动并启动该服务。

  --- 
-名称:启动使应用程序保持运行状态的服务
外壳:|
sudo systemctl守护进程重新加载
sudo systemctl启用配方。服务
sudo systemctl启动配方。服务

设置完成后,请移至该存储库以按照有关如何运行配置的说明进行操作。

链接到通过上述步骤部署的正在运行的应用程序:Yummy Recipes API