Adrian 用 pyinfra 演示纯 Python 部署两个网站
来源标题:Pyinfra – simple infrastructure automation in Python
Adrian 在 DevOps 聚会上用 pyinfra 做了现场演示,仅用 Python 代码就将落地页和 Python Web 应用先部署到本地虚拟机,再部署到两台远程服务器。pyinfra 是一个主要面向命令行的工具,能把 Python 代码转换成 shell 命令,并通过 SSH 在多台服务器上并行执行,定位类似 Ansible 但更简单。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
大家好,我是Adrian,今天我将现场演示pyinfra,一个基础设施自动化工具。我们将只用Python代码部署两个网站——一个落地页和一个Python Web应用——先在本地虚拟机上部署,然后在两台远程服务器上部署。这是我在本地DevOps聚会上所做演讲的编辑版文字记录。虽然写作中丢失了部分“现场”感,但我认为这是一份相当不错的pyinfra教程,欢迎你在家跟着做。
在讨论pyinfra之前,我应该先介绍一下自己。我职业生涯的大部分时间在一家财富10强公司工作,在那里为一些非常大的网站以及两千个较小网站背后的反向代理做站点可靠性工程,还为一家ML组织构建了一个数据湖加特征存储。业余时间,我在这里写关于Python的文章,并维护一个名字很有创意的reader——一个Python feed阅读器库和Web应用。最近我一直在做一个托管版的reader,这就是我最终用上pyinfra的原因。
pyinfra主要是一个命令行工具,它把Python代码转换成shell命令,并通过SSH在多台服务器上并行运行这些命令。可以把它想象成更简单的Ansible。
for user in ['admin', 'alice', 'bob']:
server.user(user)
files.put('files/hello.txt', '/etc/motd')
if host.data.get('install_postgres'):
apt.install('postgresql')
为什么用pyinfra?#
我选择pyinfra是因为,和Ansible一样,它是声明式的——你描述服务器应该是什么样子,pyinfra就让它变成那样——而且是幂等的——如果服务器已经处于期望状态,就什么都不做。与Ansible不同,这里没有YAML——部署(playbook)就是Python代码,这意味着你可以做Python代码能做的任何事情:你可以有for和if,你可以有代码补全和类型检查,你甚至可以导入库。
对于大规模使用Ansible的人会感兴趣的是,pyinfra也更快;在我有限的小规模经验中,它比带Mitogen插件的Ansible更快。公平地说,虽然pyinfra已经存在10年了,但它的内置操作(模块)更少,生态系统也更小,不过编写自定义操作非常容易,这在一定程度上弥补了这一点。
pyinfra的用例源于它的功能——通过SSH配置服务器。因此,pyinfra很适合无聊的、云无关的架构,从具有不同角色的大量服务器一直到单机编程,在单机编程中它仍然能让部署可重现并防止漂移。1 它也很容易学习,所以很适合自托管和家庭服务器;即使你不把它用于配置管理,pyinfra也提供了一种在服务器集群上运行临时命令的便捷方式。2
简单性伴随着一些局限:全自动流水线需要额外的工作,如果多人同时运行部署,则需要小心。尽管如此,如果你把部署结构组织好,你可以走得很远,而且有Python API可以在其上构建东西。
我会尽量聚焦于有趣的部分,但你可以在GitHub上找到完整代码。在演示结束时,我们将有两个网站,一个落地页和一个Python Web应用,分两个阶段部署——一个用于beta的本地虚拟机:
.--- pyinfra.local ---.- app.pyinfra.local -.
| nginx |
| static website : Python web app |
'-------------------------------------------'
……以及用于prod的两台独立服务器:
.--- pyinfra.a.c ----. .- app.pyinfra.a.c --.
| nginx | | nginx |
| static website | | Python web app |
'--------------------' '--------------------'
下面是最终部署的预览:
infra/deploy.py
apt.update(name="apt update", cache_time=24 * 3600)
apt.packages(['nginx', 'python3-certbot-nginx'], name="install nginx")
disable_default = files.link(
name="disable default site",
path='/etc/nginx/sites-enabled/default',
present=False,
)
server.service(
name="reload nginx",
service='nginx',
reloaded=True,
_if=disable_default.did_change,
)
if host.data.get('home_domain'):
local.include('tasks/home.py')
if host.data.get('app_domain'):
local.include('tasks/app.py')
操作与事实 #
首先,我们应该熟悉两个pyinfra基本概念。
操作会以某种方式改变服务器;大多数是声明式和幂等的,你用它们来确保状态。包含操作的Python文件称为部署。下面是一个简单的部署,只有一个操作,它表示“我希望hello.txt存在”:
from pyinfra.operations import files
files.file('hello.txt', present=True)
如果我们运行这个部署(下面,在我的@local机器上),我们会看到所有操作的列表,以及它们将在哪些主机上产生变更,然后被要求批准:
$ pyinfra @local examples/create_file.py
--> Loading config...
--> Loading inventory...
--> Connecting to hosts...
[@local] Connected
--> Preparing operation files...
Loading: examples/create_file.py
[@local] Ready: examples/create_file.py
--> Detected changes:
Operation Change Conditional Change
files.file (hello.txt, present=True) 1 (@local) -
...
Press enter to execute...
如果批准,我们会看到操作运行及其结果:
Press enter to execute... [Enter]
--> Beginning operation run...
--> Starting operation: files.file (hello.txt, present=True)
[@local] Success
--> Results:
Operation Hosts Success Error No Change
files.file (hello.txt, present=True) 1 1 - -
Grand total 1 1 - -
--> Disconnecting from hosts...
现在hello.txt存在了:
$ ls hello.txt
hello.txt
由于files.file是幂等的,如果我们再次运行部署,什么都不会发生:
$ pyinfra @local examples/create_file.py
...
--> Detected changes:
Operation Change Conditional Change
files.file (hello.txt, present=True) - -
...
--> Beginning operation run...
--> Starting operation: files.file (hello.txt, present=True)
[@local] No changes
...
事实收集关于目标主机的数据;你用它们来控制操作。下面是一个安装Apache Web服务器的部署:
from pyinfra import host
from pyinfra.facts.server import LinuxName
(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。