LinchPin:一個使用 Ansible 的簡化的編配工具

Clint Savage發表於2017-12-21

2016 年末開始的 LinchPin,現在已經擁有一個 Python API 和一個成長中的社群。

去年,我的團隊公佈了 LinchPin,這是一個使用 Ansible 的混合雲編配orchestration工具。配給provision雲資源從來沒有這麼容易便捷過。藉助 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是一個定義好的檔案系統路徑,它是一個邏輯上的資源組。一個工作空間可以認為是一個特定環境、服務組、或其它邏輯組的一個單點。它也可以是一個所有可管理資源的大的儲存容器。

工作空間可以在命令列上使用 --workspace-w) 選項去指定,隨後是工作空間路徑。它也可以使用環境變數指定(比如,bash 中的 $WORKSPACE)。預設工作空間是當前目錄。

初始化 (linchpin init)

執行 linchpin init 將生成一個需要的目錄結構,以及一個 PinFiletopology、和 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 的網路。會生成一個庫存inventory,並放在 inventories/libvirt.inventory 目錄中。它可以通過讀取 topologies/example-topology.yml 和 topology_name 的值瞭解它。

配給provisioning (linchpin up)

一旦有了一個 PinFile、拓撲、和一個可選的佈局,就可以配給provisioning了。

我們使用 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 的更多詳細情況,可以去看示例

庫存inventory生成

作為上面提到的 PinFile 的一部分,可以指定一個 layout。如果這個檔案被指定,並且放在一個正確的位置上,就會為配給的資源自動生成一個用於 Ansible 的靜態庫存inventory檔案:

---
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 是冪等的idempotentlinchpin 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: 在配給拓撲資源之後執行,並且生成可選的庫存inventory
  • predestroy: 解除安裝拓撲資源之前執行
  • postdestroy: 解除安裝拓撲資源之後執行

在每種狀態下,這些 hooks 允許執行外部指令碼。存在幾種型別的 hook,包括一個定製的叫做 Action Managers。這是一個內建的 Action Manager 的列表:

  • shell: 允許任何的內聯inline的 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 節。使用 openstackec2、和 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

本文由 LCTT 原創編譯,Linux中國 榮譽推出

相關文章