LinchPin:一個使用 Ansible 的簡化的編配工具
去年,我的團隊公布了 LinchPin,這是一個使用 Ansible 的混合雲 編配 工具。 配給 雲資源從來沒有這麼容易便捷過。藉助 Ansible 強力支持,LinchPin 專註於簡化,使雲資源讓用戶可以觸手可及。在這篇文章中,我將介紹 LinchPin,並且去看看過去的 10 個月該項目是如何逐漸成熟。
(LCTT 譯註:關於 orchestration 應該翻譯成慣例的「編排」還是「編配」,有個 @wffger 提出的建議 ,歡迎大家參與討論。)
LinchPin 剛出現的時候,使用 ansible-playbook
命令去運行 LinchPin ,雖然可以完成,但是還是很複雜的,LinchPin 現在有一個前端命令行用戶界面(CLI),它是用 Click 寫的,而且它使 LinchPin 比以前更簡化。
沒有止步於 CLI,LinchPin 現在還有一個 Python API,它可以用於管理資源,比如,Amazon EC2 和 OpenStack 實例、網路、存儲、安全組等等。這個 API 文檔 可以在你想去嘗試 LinchPin 的 Python API 時幫助你。
Playbook 是一個庫
因為 LinchPin 的核心是 Ansible playbook,其角色、模塊、過濾器,以及任何被稱為 Ansible 模塊的東西都被移進 LinchPin 庫中,這意味著我們雖然可以直接調用 playbook,但它不是資源管理的首選機制。linchpin
可執行文件事實上已經成為該命令行的前端。
深入了解命令行
讓我們深入了解 linchpin
命令行:
$ linchpin
Usage: linchpin [OPTIONS] COMMAND [ARGS]...
linchpin: hybrid cloud orchestration
Options:
-c, --config PATH Path to config file
-w, --workspace PATH Use the specified workspace if the familiar Jenkins
$WORKSPACE environment variable is not set
-v, --verbose Enable verbose output
--version Prints the version and exits
--creds-path PATH Use the specified credentials path if WORKSPACE
environment variable is not set
-h, --help Show this message and exit.
Commands:
init Initializes a linchpin project.
up Provisions nodes from the given target(s) in...
destroy Destroys nodes from the given target(s) in...
你可以立即看到一個簡單的描述,以及命令的選項和參數。這個幫助的最下面的三個命令是本文的重點內容。
配置文件
之前有個名為 linchpin_config.yml
的文件。但現在這個文件沒有了,替換它的是一個 ini 形式的配置文件,稱為 linchpin.conf
。雖然這個文件可以被修改或放到別的地方,它可以放置在配置文件容易找到的庫路徑中。在多數情況下,linchpin.conf
文件是不需要去修改的。
工作空間
工作空間 是一個定義好的文件系統路徑,它是一個邏輯上的資源組。一個工作空間可以認為是一個特定環境、服務組、或其它邏輯組的一個單點。它也可以是一個所有可管理資源的大的存儲容器。
工作空間可以在命令行上使用 --workspace
(-w
) 選項去指定,隨後是工作空間路徑。它也可以使用環境變數指定(比如,bash 中的 $WORKSPACE
)。默認工作空間是當前目錄。
初始化 (linchpin init
)
運行 linchpin init
將生成一個需要的目錄結構,以及一個 PinFile
、topology
、和 layout
文件的示例:
$ export WORKSPACE=/tmp/workspace
$ linchpin init
PinFile and file structure created at /tmp/workspace
$ cd /tmp/workspace/
$ tree
.
├── credentials
├── hooks
├── inventories
├── layouts
│ └── example-layout.yml
├── PinFile
├── resources
└── topologies
└── example-topology.yml
在這個時候,可以執行 linchpin up
,然後提供一個 libvirt
虛擬機,和一個名為 linchpin-centos71
的網路。會生成一個 庫存 ,並放在 inventories/libvirt.inventory
目錄中。它可以通過讀取 topologies/example-topology.yml
和 topology_name
的值了解它。
配給 (linchpin up
)
一旦有了一個 PinFile、拓撲、和一個可選的布局,就可以 配給 了。
我們使用 dummy (模擬)工具,因為用它來配給非常簡單;它不需要任何額外的東西(認證、網路、等等)。dummy 配給程序會創建一個臨時文件,它表示所配給的主機。如果臨時文件沒有任何數據,說明主機沒有被配給,或者它已經被銷毀了。
dummy 配給程序的目錄樹大致如下:
$ tree
.
├── hooks
├── inventories
├── layouts
│ └── dummy-layout.yml
├── PinFile
├── resources
└── topologies
└── dummy-cluster.yml
PinFile 也很簡單;它指定了它的拓撲,並且為 dummy1
目標提供一個可選的布局:
dummy1:
topology: dummy-cluster.yml
layout: dummy-layout.yml
dummy-cluster.yml
拓撲文件是一個引用,指向到配給的三個 dummy_node
類型的資源:
topology_name: "dummy_cluster" # topology name
resource_groups:
-
resource_group_name: "dummy"
resource_group_type: "dummy"
resource_definitions:
-
name: "web"
type: "dummy_node"
count: 3
執行命令 linchpin up
將基於上面的 topology_name
(在這個案例中是 dummy_cluster
)生成 resources
和 inventory
文件。
$ linchpin up
target: dummy1, action: up
$ ls {resources,inventories}/dummy*
inventories/dummy_cluster.inventory resources/dummy_cluster.output
要驗證 dummy 集群的資源,可以檢查 /tmp/dummy.hosts
:
$ cat /tmp/dummy.hosts
web-0.example.net
web-1.example.net
web-2.example.net
Dummy 模塊為假定的(或模擬的)配給提供了一個基本工具。關於在 OpenStack、AWS EC2、Google Cloud 上和 LinchPin 的更多詳細情況,可以去看示例。
庫存 生成
作為上面提到的 PinFile 的一部分,可以指定一個 layout
。如果這個文件被指定,並且放在一個正確的位置上,就會為配給的資源自動生成一個用於 Ansible 的靜態 庫存 文件:
inventory_layout:
vars:
hostname: __IP__
hosts:
example-node:
count: 3
host_groups:
- example
當 linchpin up
運行完成,資源文件將提供一個很有用的詳細信息。特別是,插入到靜態庫存的 IP 地址或主機名:
[example]
web-2.example.net hostname=web-2.example.net
web-1.example.net hostname=web-1.example.net
web-0.example.net hostname=web-0.example.net
[all]
web-2.example.net hostname=web-2.example.net
web-1.example.net hostname=web-1.example.net
web-0.example.net hostname=web-0.example.net
卸載 (linchpin destroy
)
LinchPin 也可以執行資源卸載。卸載動作一般認為該資源是已經配給好的;然而,因為 Ansible 是 冪等的 ,linchpin destroy
將僅檢查確認該資源是啟用的。如果這個資源已經是啟用的,它將去卸載它。
命令 linchpin destroy
也將使用資源和/或拓撲文件去決定合適的卸載過程。
Ansible dummy
角色不使用資源,卸載期間僅有拓撲:
$ linchpin destroy
target: dummy1, action: destroy
$ cat /tmp/dummy.hosts
-- EMPTY FILE --
針對暫時的資源,卸載功能有一些限制,像網路、存儲、等等。網路資源可以被用於多個雲實例。在這種情況下,執行一個 linchpin destroy
某些資源就不能卸載。這取決於每個供應商的實現。查看每個供應商的具體實現。
LinchPin 的 Python API
在 linchpin
命令行中實現的功能大多數都是用 Python API 寫的。這個 API,雖然不完整,但它已經成為 LinchPin 工具的至關重要的組件。
這個 API 由下面的三個包組成:
linchpin
linchpin.cli
linchpin.api
該命令行工具是基於 linchpin
包來管理的。它導入了 linchpin.cli
模塊和類,該類是 linchpin.api
的子類。這樣做的目的是為了允許使用 linchpin.api
來做其它的 LinchPin 實現,比如像計劃中的 RESTful API。
更多信息,去查看 Python API library documentation on Read the Docs。
Hook
LinchPin 1.0 的其中一個大的變化是轉向 hook。hook 的目標是在 linchpin
運行期間的特定狀態下,允許配置使用更多外部資源。目前的狀態有:
preup
: 在配給拓撲資源之前運行postup
: 在配給拓撲資源之後運行,並且生成可選的 庫存predestroy
: 卸載拓撲資源之前運行postdestroy
: 卸載拓撲資源之後運行
在每種狀態下,這些 hooks 允許運行外部腳本。存在幾種類型的 hook,包括一個定製的叫做 Action Managers。這是一個內置的 Action Manager 的列表:
shell
: 允許任何的 內聯 的 shell 命令,或者一個可運行的 shell 腳本python
: 運行一個 Python 腳本ansible
: 運行一個 Ansible playbook,允許傳遞一個vars_file
和extra_vars
作為 Python 字典nodejs
: 運行一個 Node.js 腳本ruby
: 運行一個 Ruby 腳本
hook 被綁定到一個特定的目標,並且每個目標使用時必須重新聲明。將來,hook 將可能是全局的,然後它們在每個目標的 hooks
節下命名會更簡單。
使用 hook
hook 描述起來非常簡單,但理解它們強大的功能卻並不簡單。這個特性的存在是為了給用戶靈活提供那些 LinchPin 開發者所沒有考慮到的功能。這個概念可能會帶來 ping 一套系統的簡單方式,舉個實例,比如在運行另一個 hook 之前。
更仔細地去研究 工作空間 ,你可能會注意到 hooks
目錄,讓我們看一下這個目錄的結構:
$ tree hooks/
hooks/
├── ansible
│ ├── ping
│ │ └── dummy_ping.yaml
└── shell
└── database
├── init_db.sh
└── setup_db.sh
在任何情況下,hook 都可以用在 PinFile
中,展示如下:
dummy1:
topology: dummy-cluster.yml
layout: dummy-layout.yml
hooks:
postup:
- name: ping
type: ansible
actions:
- dummy_ping.yaml
- name: database
type: shell
actions:
- setup_db.sh
- init_db.sh
基本概念是有三個 postup 動作要完成。Hook 是從上到下運行的,因此,Ansible ping
任務將首先運行,緊接著是兩個 shell 任務, setup_db.sh
和 init_db.sh
。假設 hook 運行成功。將發生一個系統的 ping,然後,一個資料庫被安裝和初始化。
認證的驅動程序
在 LinchPin 的最初設計中,開發者決定在 Ansible playbooks 中管理認證;然而,逐漸有更多的 API 和命令行驅動的工具後,意味著認證將被置於 playbooks 庫之外,並且還可以根據需要去傳遞認證值。
配置
讓用戶使用驅動程序提供的認證方法去完成這個任務。舉個實例,如果對於 OpenStack 調用的拓撲,標準方法是使用一個 yaml 文件,或者類似於 OS_
前綴的環境變數。clouds.yaml
文件是一個 profile 文件的組成部分,它有一個 auth
節:
clouds:
default:
auth:
auth_url: http://stack.example.com:5000/v2.0/
project_name: factory2
username: factory-user
password: password-is-not-a-good-password
更多詳細信息在 OpenStack documentation。
這個 clouds.yaml
或者任何其它認證文件位於 default_credentials_path
(比如,~/.config/linchpin
)中,並在拓撲中引用:
topology_name: openstack-test
resource_groups:
-
resource_group_name: linchpin
resource_group_type: openstack
resource_definitions:
- name: resource
type: os_server
flavor: m1.small
image: rhel-7.2-server-x86_64-released
count: 1
keypair: test-key
networks:
- test-net2
fip_pool: 10.0.72.0/24
credentials:
filename: clouds.yaml
profile: default
default_credentials_path
可以通過修改 linchpin.conf
改變。
拓撲在底部包含一個新的 credentials
節。使用 openstack
、ec2
、和 gcloud
模塊,也可以去指定類似的憑據。認證驅動程序將查看給定的名為 clouds.yaml
的文件,並搜索名為 default
的 配置。
假設認證被找到並被載入,配給將正常繼續。
簡化
雖然 LinchPin 可以完成複雜的拓撲、庫存布局、hooks、和認證管理,但是,終極目標是簡化。通過使用一個命令行界面的簡化,除了提升已經完成的 1.0 版的開發者體驗外,LinchPin 將持續去展示複雜的配置可以很簡單地去管理。
社區的成長
在過去的一年中,LinchPin 的社區現在已經有了 郵件列表和一個 IRC 頻道(#linchpin on chat.freenode.net,而且在 GitHub 中我們很努力地管理它。
在過去的一年裡,社區成員已經從 2 位核心開發者增加到大約 10 位貢獻者。更多的人持續參與到項目中。如果你對 LinchPin 感興趣,可以給我們寫信、在 GitHub 上提問,加入 IRC,或者給我們發郵件。
這篇文章是基於 Clint Savage 在 OpenWest 上的演講 Introducing LinchPin: Hybrid cloud provisioning using Ansible 整理的。OpenWest 將在 2017 年 7 月 12-15 日在鹽城湖市舉行。
作者簡介:
Clint Savage - 工作於 Red Hat 是一位負責原子項目(Project Atomic)的高級軟體工程師。他的工作是為 Fedora、CentOS、和 Red Hat Enterprise Linux(RHEL)提供自動原子伺服器構建。
via: https://opensource.com/article/17/6/linchpin
作者:Clint Savage 譯者:qhwdw 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive