SaltStack State Requisites - 狀態配置中的必要性依賴條件的使用方法介紹

Requisites - 必要條件

您也可以參考在Github上維護的這一份技術資料:Requisites and Other Global State Arguments

Salt requisite 系統用於創建狀態之間的關係。 核心思想是,當一種狀態某種程度上依賴於另一種狀態時,可以輕鬆定義相互依賴。 這些依賴性通過使用狀態名稱和ID或名稱聲明關係來表示。 必需目標的一般形式是<state name> : <ID or name>。 這種特定形式定義爲 Requisite Reference

Requisite 分爲兩種類型:direct requisites(例如require)和requisite_ins(例如require_in)。 關係是有方向的:直接的先決條件需要其他狀態的某些條件。 但是,Requisite_in將必需項插入指向目標狀態的目標狀態。 下面的示例演示了直接的必要條件:

vim:
  pkg.installed

/etc/vimrc:
  file.managed:
    - source: salt://edit/vimrc
    - require:
      - pkg: vim

在上面的示例中,文件/etc/vimrc的配置取決於vim軟件包是否已安裝。

requisite_in語句則相反。 Requisite_ins不會說“我依賴某事”,而是說“某人依賴我”:

vim:
  pkg.installed:
    - require_in:
      - file: /etc/vimrc

/etc/vimrc:
  file.managed:
    - source: salt://edit/vimrc

因此,在這裏,使用requisite_in可以完成與第一個示例相同的操作,但反之亦然。 vim軟件包說“/etc/vimrc取決於我”。 這將導致將require插入到針對vim狀態的/etc/vimrc狀態。

最後,將創建一個依賴關係圖,並以有限且可預測的順序執行所有操作。

Requisite matching - 必要性條件的匹配方法

Requisites 需要兩條信息進行匹配:狀態模塊名稱-例如 pkg 和標識符,例如 vim ,可以是ID(節的第一行)或-name參數。

- require:
  - pkg: vim

Omitting state module in requisites - 在必要條件中省略狀態模塊

New in version 2016.3.0.

在版本2016.3.0中,狀態模塊名稱被設置爲可選。 如果省略狀態模塊,則將要求與ID匹配的所有狀態,無論它們使用的是哪個模塊。

- require:
  - vim

State target matching - 目標狀態匹配

爲了瞭解如何匹配狀態目標,瞭解狀態編譯器的工作方式將很有幫助。 考慮以下示例:

Deploy server package:
  file.managed:
    - name: /usr/local/share/myapp.tar.xz
    - source: salt://myapp.tar.xz

Extract server package:
  archive.extracted:
    - name: /usr/local/share/myapp
    - source: /usr/local/share/myapp.tar.xz
    - archive_format: tar
    - onchanges:
      - file: Deploy server package

第一個公式將轉換爲字典,如下所示(以YAML表示,爲簡化起見,省略了一些屬性)爲高級數據:

Deploy server package:
  file:
    - managed
    - name: /usr/local/share/myapp.tar.xz
    - source: salt://myapp.tar.xz

公式中使用的file.managed格式本質上是語法糖:最後,目標是file,在上面的Extract server package狀態中使用了file

Identifier matching

ID聲明和name參數要求都匹配。 這意味着,在上面的“Deploy server package”示例中,require requisite必須與Deploy server package/usr/local/share/myapp.tar.xz匹配,因此以下兩個版本的“ Extract server package”均可使用 :

# (Archive arguments omitted for simplicity)

# Match by ID declaration
Extract server package:
  archive.extracted:
    - onchanges:
      - file: Deploy server package

# Match by name parameter
Extract server package:
  archive.extracted:
    - onchanges:
      - file: /usr/local/share/myapp.tar.xz

Requisite overview - 必要性條件一覽表

name of requisite state is only executed if target execution result is state is only executed if target has changes order 1.target 2.state (default) comment or description
require success default state will always execute unless target fails
watch success default like require, but adds additional behaviour (mod_watch)
prereq success has changes (run individually as dry-run) switched like onchanges, except order
onchanges success has changes default execute state if target execution result is success and target has changes
onfail failed default Only requisite where state exec. if target fails

在這個表格中使用了以下簡寫形式:

state (= dependent state): state containing requisite

target (= state target) : state referenced by requisite

Direct Requisite and Requisite_in types

下面列表是可以在 Salt 中使用的直接必要性條件:

  • require
  • watch
  • prereq
  • use
  • onchanges
  • onfail

每一個直接必要性條件都有一個相應的 requisite_in條件:

  • require_in
  • watch_in
  • prereq_in
  • use_in
  • onchanges_in
  • onfail_in

其中有幾個必要條件還支持使用 requisite_any 形式的聲明:

  • require_any
  • watch_any
  • onchanges_any
  • onfail_any

所有必要條件都定義了特定的關係,並且始終與上面定義的依賴關係邏輯一起工作。

require

使用require要求必需狀態在從屬狀態之前執行。 包含需求條件的狀態定義爲從屬狀態。 require語句中指定的狀態定義爲必需狀態。 如果所需狀態的執行成功,則從屬狀態將執行。 如果所需狀態的執行失敗,則從屬狀態將不會執行。 在上面的第一個示例中,文件/etc/vimrc僅在成功安裝vim軟件包後才執行。

Require an Entire SLS File - 依賴於一個SLS文件

從Salt 0.16.0開始,可以依賴於一個完整的sls文件。 爲此,首先要include sls文件,然後將狀態設置爲要求依賴於包含的sls文件:

include:
  - foo

bar:
  pkg.installed:
    - require:
      - sls: foo

這將添加在給定的sls文件中找到的所有狀態聲明。 這意味着將需要依賴於sls foo中的每個狀態。 這使得在任何必要性定義的語句中輕鬆批處理大批狀態非常容易。

require_any

New in version 2018.3.0.

使用require_any要求至少有必需狀態之一在從屬狀態之前執行。 包含require_any必要條件的狀態定義爲從屬狀態。 require_any語句中指定的狀態定義爲必需狀態。 如果所需狀態的執行至少有一個成功了,則將執行從屬狀態。 如果所有必需狀態的執行均失敗,則從屬狀態將不會執行。

A:
  cmd.run:
    - name: echo A
    - require_any:
      - cmd: B
      - cmd: C
      - cmd: D
B:
  cmd.run:
    - name: echo B

C:
  cmd.run:
    - name: /bin/false

D:
  cmd.run:
    - name: echo D

在此示例中,A將運行,因爲指定的需求B,C或D中的至少一個將成功。

watch

當其他狀態發生變化時,watch語句用於添加由以上狀態變化可以引發的其他行爲。

注意:如果一個狀態僅在另一個狀態發生更改時才執行,否則什麼也不做,則應使用新的onchanges要求而不是watchwatch旨在在發生更改時添加其他行爲,否則狀態將正常執行。

包含watch條件的狀態被定義爲watch狀態watch語句中指定的狀態被定義爲watched狀態。 當watch狀態執行時,它將返回一個包含名爲“ changes”的鍵的字典。 下面是狀態返回字典的兩個示例,爲清楚起見,顯示在json中:

{
    "local": {
        "file_|-/tmp/foo_|-/tmp/foo_|-directory": {
            "comment": "Directory /tmp/foo updated",
            "__run_num__": 0,
            "changes": {
                "user": "bar"
            },
            "name": "/tmp/foo",
            "result": true
        }
    }
}

{
    "local": {
        "pkgrepo_|-salt-minion_|-salt-minion_|-managed": {
            "comment": "Package repo 'salt-minion' already configured",
            "__run_num__": 0,
            "changes": {},
            "name": "salt-minion",
            "result": true
        }
    }
}

如果watch狀態的“result”爲True,則watch狀態將正常執行;如果爲False,則watch狀態將永遠不會運行。watch語句的此部分是複製了require組件的功能。

如果watch狀態的“result”爲True,並且“changes”鍵包含填充的詞典(更改在watched狀態下發生),則watch requisite可以添加其他行爲。此附加行爲由watch狀態模塊中的mod_watch函數定義。如果在watch狀態模塊中存在mod_watch函數,則除了正常watch狀態外還將調用該函數。在這種情況下,從mod_watch函數返回的數據將被返回給master服務器,而從主監視功能返回的數據將被丟棄。

如果“ changes”鍵包含一個空字典,則watch條件的行爲與require必需的行爲完全相同(watch狀態將在“result”爲True時執行,而在“result”爲False時失敗)。

注意:並非所有狀態模塊都包含mod_watch。如果watch狀態模塊中缺少mod_watch,則watch條件的行爲與require條件的行爲完全相同。

使用watch的一個很好的例子是service.running狀態。當service監視一個狀態時,除了Salt確保服務正在運行之外,還會在監視狀態更改時重新加載/重新啓動服務。

ntpd:
  service.running:
    - watch:
      - file: /etc/ntp.conf
  file.managed:
    - name: /etc/ntp.conf
    - source: salt://ntp/files/ntp.conf

watch_any

New in version 2018.3.0.

包含watch_any必要條件的狀態被定義爲監視狀態。 watch_any語句中指定的狀態被定義爲watched狀態。當受監視的狀態執行時,它們將返回包含名爲“changes”的鍵的字典。

如果任何被監視狀態的“result”爲True,則監視狀態將正常執行,如果所有狀態均爲False,則監視狀態將永遠不會運行。watch的此部分複製了require組件的功能。

如果任何被監視狀態的“result”爲True,並且“changes”鍵包含填充了數據的詞典(在watched狀態下發生了更改),則watch requisite條件可以添加其他行爲。此附加行爲由watch狀態模塊中的mod_watch函數定義。如果在監視狀態模塊中存在mod_watch函數,則除了正常監視狀態外還將調用該函數。在這種情況下,從mod_watch函數返回的數據將被返回給master服務器,而主監視功能的返回數據將被丟棄。

如果“changes”鍵包含一個空字典,則watch條件的行爲與require必需的行爲完全相同(watch狀態將在“result”爲True時執行,而在“result”爲False時失敗)。

apache2:
  service.running:
    - watch_any:
      - file: /etc/apache2/sites-available/site1.conf
      - file: apache2-site2
  file.managed:
    - name: /etc/apache2/sites-available/site1.conf
    - source: salt://apache2/files/site1.conf
apache2-site2:
  file.managed:
    - name: /etc/apache2/sites-available/site2.conf
    - source: salt://apache2/files/site2.conf

在此示例中,如果兩個file.managed狀態之一的結果爲True且已更改,則將重新加載/重新啓動服務。

prereq

New in version 0.16.0.

prereq允許根據尚未執行的狀態的預期結果採取措施。包含prereq條件的狀態被定義爲pre-requiring狀態prereq語句中指定的狀態則被定義爲pre-required狀態。

評估prereq條件後,pre-required狀態會報告是否需要任何更改。通過啓用test = True,將pre-required的單個狀態作爲測試運行來完成。該測試運行將返回一個包含名爲“changes”的鍵的字典。 (有關“changes”詞典的示例,請參見上面的watch部分。)

如果“changes”鍵包含一個已填充數據的字典,則意味着pre-required的狀態期望在實際執行該狀態時發生更改。pre-requiring狀態現在將實際運行。如果pre-requiring狀態成功執行,則將繼續執行pre-required狀態。如果pre-requiring狀態失敗,則將不會執行pre-required狀態。

如果“changes”鍵包含一個空的詞典,則意味着pre-required狀態將不會發生更改。此時,既不會執行pre-requiring狀態,也不會運行pre-required狀態。

在以下實際示例中顯示了定義prereq的最佳方式:當由於底層代碼將要更改而應關閉服務時,在進行更新時該服務應脫機。在此示例中,graceful-downpre-requiring的狀態,而site-codepre-required的狀態。

graceful-down:
  cmd.run:
    - name: service apache graceful
    - prereq:
      - file: site-code

site-code:
  file.recurse:
    - name: /opt/site_code
    - source: salt://site/code

在這種情況下,僅當site-code狀態希望通過file.recurse調用部署新代碼時,纔會關閉apache服務器。 只有正常運行正常完成後,纔會執行site-code部署。

onfail

New in version 2014.7.0.

onfail必要條件允許嚴格響應於另一個狀態的失敗而發生反應。 這可以通過多種方式使用,例如由於失敗而執行第二次嘗試來設置服務或開始執行單獨的狀態線程。

onfail要求的應用方式與watch的要求相同:

primary_mount:
  mount.mounted:
    - name: /mnt/share
    - device: 10.0.0.45:/share
    - fstype: nfs

backup_mount:
  mount.mounted:
    - name: /mnt/share
    - device: 192.168.40.34:/share
    - fstype: nfs
    - onfail:
      - mount: primary_mount

注意:將failhard(全局或在某個故障狀態中)設置爲True將導致忽略onfailonfail_inonfail_any需求。 如果要將設置爲True的全局failhardonfailonfail_inonfail_any組合在一起,則必須在可能發生失敗的狀態下將failhard顯式設置爲False(覆蓋全局設置)。

注意:從Salt的2016.11.0版本開始,onfail對多個列出的onfail要求使用OR邏輯。 在2016.11.0發行版之前,onfail使用AND邏輯。 有關更多信息,請參見問題#22370

onfail_any

New in version 2018.3.0.

onfail_any必要條件允許嚴格響應作爲對至少一個其他狀態失敗的響應而發生。 這可以通過多種方式使用,例如由於失敗而執行第二次嘗試來設置服務或開始執行單獨的狀態線程。

onfail_any必要條件的使用方式與require_anywatch_any相同:

primary_mount:
  mount.mounted:
    - name: /mnt/share
    - device: 10.0.0.45:/share
    - fstype: nfs

secondary_mount:
  mount.mounted:
    - name: /mnt/code
    - device: 10.0.0.45:/code
    - fstype: nfs

backup_mount:
  mount.mounted:
    - name: /mnt/share
    - device: 192.168.40.34:/share
    - fstype: nfs
    - onfail_any:
      - mount: primary_mount
      - mount: secondary_mount

在此示例中,如果primary_mountsecondary_mount狀態中的任何一個導致失敗,則將裝載backup_mount

onchanges

New in version 2014.7.0.

onchanges必要條件使狀態僅在必需狀態發生更改並且watched狀態的“result”爲True時才適用。 這可能是更改系統後執行一個post hook操作的有用方法。

如果一個狀態具有多個onchanges要求,則如果任何watched狀態發生變化,則該狀態將觸發。

注意:一個容易犯的錯誤是在應該使用onchanges時使用onchanges_in。 例如,以下配置不正確:

myservice:
  pkg.installed:
    - name: myservice
  file.managed:
    - name: /etc/myservice/myservice.conf
    - source: salt://myservice/files/myservice.conf
    - mode: 600
  cmd.run:
    - name: /usr/libexec/myservice/post-changes-hook.sh
    - onchanges_in:
      - file: /etc/myservice/myservice.conf

這將建立一個必要性依賴的關係,其中cmd.run狀態始終執行,而file.managed狀態僅在cmd.run狀態發生更改時才執行(因爲cmd.run狀態將命令結果包括爲 變化)。

從語義上看,cmd.run狀態應該僅在文件狀態發生更改時才運行,但請記住,必需關係涉及一個狀態監視另一個狀態,而Required_in則相反:它強制指定狀態監視使用了Required_in聲明的狀態 。

正確的用法是:

myservice:
  pkg.installed:
    - name: myservice
  file.managed:
    - name: /etc/myservice/myservice.conf
    - source: salt://myservice/files/myservice.conf
    - mode: 600
  cmd.run:
    - name: /usr/libexec/myservice/post-changes-hook.sh
    - onchanges:
      - file: /etc/myservice/myservice.conf

onchanges_any

New in version 2018.3.0.

onchanges_any必需條件使一個狀態僅應用其中一個必需的狀態就能生成更改,如果watched狀態之一的“結果”爲True。 這可能是更改系統方面後執行post hook的一個有用方法。

myservice:
  pkg.installed:
    - name: myservice
    - name: yourservice
  file.managed:
    - name: /etc/myservice/myservice.conf
    - source: salt://myservice/files/myservice.conf
    - mode: 600
  file.managed:
    - name: /etc/yourservice/yourservice.conf
    - source: salt://yourservice/files/yourservice.conf
    - mode: 600
  cmd.run:
    - name: /usr/libexec/myservice/post-changes-hook.sh
    - onchanges_any:
      - file: /etc/myservice/myservice.conf
      - file: /etc/your_service/yourservice.conf

在此示例中,僅當file.managed狀態中的任何一個生成更改並且至少一個受監視狀態的“result”爲True時,才運行cmd.run

use

use必要條件用於繼承另一個id聲明中傳遞的參數。 當許多文件需要具有相同的默認值時,這很有用。

/etc/foo.conf:
  file.managed:
    - source: salt://foo.conf
    - template: jinja
    - mkdirs: True
    - user: apache
    - group: apache
    - mode: 755

/etc/bar.conf:
  file.managed:
    - source: salt://bar.conf
    - use:
      - file: /etc/foo.conf

use聲明主要是針對networking狀態而開發的,但可以在Salt的任何狀態中使用。 這對於networking狀態很有意義,因爲它可以定義一長列選項,這些選項需要應用於多個網絡接口。

use語句不繼承目標狀態的必要性條件參數。 這也意味着一系列use條件不會繼承"繼承的選項"。

runas

New in version 2017.7.0.

runas全局選項用於設置用戶,該用戶將用於在cmd.run模塊中運行命令。

django:
  pip.installed:
    - name: django >= 1.6, <= 1.7
    - runas: daniel
    - require:
      - pkg: python-pip

在上述狀態下,由cmd.run運行的pip命令將由daniel用戶運行。

runas_password

New in version 2017.7.2.

runas_password全局選項用於設置runas全局選項使用的密碼。 指定runas時,Windows上的cmd.run要求使用此命令。 在狀態中定義runas_password時將設置它。

run_script:
  cmd.run:
    - name: Powershell -NonInteractive -ExecutionPolicy Bypass -File C:\\Temp\\script.ps1
    - runas: frank
    - runas_password: supersecret

在上述狀態下,由cmd.run運行的Powershell腳本將由frank用戶使用supersecret密碼運行。

The _in versions of requisites

所有的requisites組件還具有相應的Requires_in版本,其版本與常規副本相反。 下面的所有示例均以require_in爲例,但請注意,所有_in requisites條件的工作方式均相同:它們在目標狀態下產生正常的必備條件,該目標狀態以定義了Required_in的狀態爲目標。 因此,require_in導致target狀態會依賴於targeting狀態。 類似地,watch_in使target狀態監視targeting狀態。

如果一個狀態聲明需要被另一個狀態聲明所依賴,則require_in可以實現這一點。 因此,這兩個sls文件最後將是相同的:

Using require

httpd:
  pkg.installed: []
  service.running:
    - require:
      - pkg: httpd

Using require_in

httpd:
  pkg.installed:
    - require_in:
      - service: httpd
  service.running: []

在單獨的sls文件中分配require時,require_in語句特別有用。 例如,httpd可能需要用於設置PHP或mod_python的組件,這很常見,但是HTTP狀態不需要在設置時就知道需要它的其他組件:

http.sls

httpd:
  pkg.installed: []
  service.running:
    - require:
      - pkg: httpd

php.sls

include:
  - http

php:
  pkg.installed:
    - require_in:
      - service: httpd

mod_python.sls

include:
  - http

mod_python:
  pkg.installed:
    - require_in:
      - service: httpd

現在,只有首先驗證phpmod_python都已安裝,才能啓動httpd服務器。 因此,這將允許在“事後”定義一個條件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章