Ansible 中變量的系統方法

ansible devops 程式碼風格

嘿! 我的名字是 丹尼斯·卡柳日內 我在開發流程自動化部門擔任工程師。 每天,新的應用程式版本都會在數百個活動伺服器上推出。 在這篇文章中,我分享了我使用 Ansible 來實現這些目的的經驗。

本指南提供了一種在部署中組織變數的方法。 本指南適用於那些已經在劇本中使用角色並閱讀過的人 最佳實踐,但面臨類似的問題:

  • 在程式碼中找到一個變數後,不可能立即明白它負責什麼;
  • 角色有好幾個,變數需要與一個值關聯,但就是不行;
  • 難以向他人解釋你的劇本中變數的邏輯如何運作

我們在公司的專案中遇到了這些問題,因此我們在playbook中製定了變數設計規則,在一定程度上解決了這些問題。

Ansible 中變量的系統方法

角色中的變數

角色是部署系統的一個單獨的物件。 與任何系統物件一樣,它必須具有與系統其餘部分互動的介面。 這樣的介面就是角色變數。

我們以角色為例 api,它會在伺服器上安裝 Java 應用程式。 它可能有哪些變數?

Ansible 中變量的系統方法

變數角色依類型可分為2種:

1. Свойства
    a) независимые от среды
    б) зависимые от среды
2. Связи
    a) слушатели 
    б) запросы внутри системы
    в) запросы в среду

可變屬性 是決定角色行為的變數。

查詢變數 - 這些變數的值用於指定角色外部的資源。

可變監聽器 - 這些變數的值用於形成請求變數。

另一方面,1a、2a、2b是不依賴環境(硬體、外部資源等)的變量,可以在defaults角色中填入預設值。 然而,不可能用「example」以外的值填充類型1.b和2.c的變量,因為它們會根據環境的不同而變化。

程式碼風格

  • 變數名稱必須以角色名稱開頭。 這將使將來很容易弄清楚該變數來自什麼角色以及它負責什麼。
  • 在角色中使用變數時,請務必遵循封裝的原則,使用角色本身或目前角色所依賴的角色中定義的變數。
  • 避免使用字典作為變數。 Ansible 不允許您方便地覆寫字典中的單一值。

    錯誤變數的範例:

    myrole_user:
        login: admin
        password: admin

    這裡登入名是自變量,密碼是因變數。 但
    因為它們被組合成一個字典,所以你必須完整地指定它
    總是。 這是非常不方便的。 這樣更好:

    myrole_user_login: admin
    myrole_user_password: admin

部署手冊中的變數

在編譯部署 playbook(以下簡稱 playbook)時,我們遵循將其放置在單獨的儲存庫中的規則。 與角色相同:每個角色都有自己的 git 儲存庫。 這使您可以理解角色和劇本是部署系統的不同獨立對象,一個對象的變更不應影響另一個對象的操作。 這是透過改變變數的預設值來實現的。

總而言之,在編譯劇本時,可以在兩個地方覆蓋角色變數的預設值:劇本變數和庫存變數。

mydeploy                        # Каталог деплоя
├── deploy.yml                  # Плейбук деплоя
├── group_vars                  # Каталог переменных плейбука
│   ├── all.yml                 # Файл для переменных связи всей системы
│   └── myapi.yml               # Файл переменных свойств группы myapi
└── inventories                 #
    └── prod                    # Каталог окружения prod
        ├── prod.ini            # Инвентори файл
        └── group_vars          # Каталог для переменных инвентори
            └── myapi           #
                ├── vars.yml    # Средозависимые переменные группы myapi
                └── vault.yml   # Секреты (всегда средозависимы) *

* — 變數和函式庫

不同之處在於,當呼叫與其位於相同等級的 playbook 時,請務必使用 playbook 變數。 這意味著這些變數非常適合更改與環境無關的變數的預設值。 相反,庫存變數將僅用於特定環境,這對於特定於環境的變數來說是理想的。

需要注意的是,變數優先權不允許您先覆寫劇本變數中的變量,然後再單獨覆寫一個清單中的變數。

這意味著在這個階段就必須確定變數是否依賴環境並將其放置在適當的位置。

例如,在一個專案中,負責啟用 SSL 的變數在很長一段時間內依賴環境,因為我們無法在其中一個展位上出於我們無法控制的原因啟用 SSL。 我們解決了這個問題後,它變得獨立於環境並轉移到劇本變數中。

組的屬性變數

讓我們透過新增 1 組具有不同 Java 應用程式但設定不同的伺服器來擴展圖 2 中的模型。

Ansible 中變量的系統方法

讓我們想像一下在這種情況下劇本會是什麼樣子:

- hosts: myapi
  roles:
    - api

- hosts: bbauth
  roles:
    - auth

- hosts: ghauth
  roles:
    - auth

我們在 playbook 中有三個群組,因此立即建議在 group_vars 庫存變數和 playbook 變數中建立相同數量的群組檔案。 在這種情況下,一組文件是對劇本中上述應用程式的一個元件的描述。 當您在劇本變數中開啟群組檔案時,您會立即看到與群組上安裝的角色的預設行為的所有差異。 庫存變數中:不同攤位的群體行為存在差異。

代碼風格

  • 盡量不要使用 host_vars 變量,因為它們不描述系統,而只是一種特殊情況,這在將來會導致問題:“為什麼這個主機與其他主機不同?”,答案不是總是很容易找到。

通訊變數

然而,這就是屬性變數的全部內容,但是通訊變數呢?
它們的區別在於它們在不同的群體中應該具有相同的含義。

起初是 這個想法 使用一個可怕的結構,例如:
hostvars[groups['bbauth'][0]]['auth_bind_port'],但他們立即拒絕了
因為它有缺點。 首先,體積大。 其次,對群組內特定主機的依賴。 第三,在開始部署之前,如果我們不想收到未定義變數的錯誤,則有必要從所有主機收集事實。

因此,決定使用通訊變數。

通訊變數 - 這些是屬於劇本的變量,需要連接系統物件。

通訊變數填入通用系統變數中 group_vars/all/vars 和 是透過從每個群組中刪除所有偵聽器變數並將偵聽器被刪除的群組的名稱新增至變數的開頭而形成的。

這確保了名稱的統一性和不重疊。

讓我們嘗試綁定上面範例中的變數:

Ansible 中變量的系統方法

假設我們有相互依賴的變數:

# roles/api/defaults:
# Переменная запроса
api_auth1_address: "http://example.com:80"
api_auth2_address: "http://example2.com:80"

# roles/auth/defaults:
# Переменная слушатель
auth_bind_port: "20000"

讓我們把它放入公共變數中 group_vars/all/vars 所有聽眾,並將組名添加到標題中:

# group_vars/all/vars
bbauth_auth_bind_port: "20000"
ghauth_auth_bind_port: "30000"

# group_vars/bbauth/vars
auth_bind_port: "{{ bbauth_auth_bind_port }}"

# group_vars/ghauth/vars
auth_bind_port: "{{ ghauth_auth_bind_port }}"

# group_vars/myapi/vars
api_auth1_address: "http://{{ bbauth_auth_service_name }}:{{ bbauth_auth_bind_port }}"
api_auth2_address: "http://{{ ghauth_auth_service_name }}:{{ ghauth_auth_bind_port }}"

現在,透過更改連接器的值,我們將確保請求將發送到連接埠所在的相同位置。

代碼風格

  • 由於角色和群組是不同的系統對象,因此它們需要具有不同的名稱,然後連結變數將準確地指示它們屬於特定的伺服器群組,而不是系統中的角色。

環境相關文件

角色可能使用因環境而異的文件。

SSL 憑證就是此類文件的一個範例。 以文字形式儲存它們
在變數中不是很方便。 但將它們的路徑儲存在變數中會很方便。

例如,我們使用變數 api_ssl_key_file: "/path/to/file".

由於很明顯密鑰憑證會隨著環境的不同而變化,因此這是一個依賴環境的變量,這意味著它應該位於檔案中
group_vars/myapi/vars 變數清單,並包含值「例如」。

在這種情況下,最方便的方法是將金鑰檔案沿著路徑放入 playbook 儲存庫中
files/prod/certs/myapi.key,那麼變數的值將是:
api_ssl_key_file: "prod/certs/myapi.key"。 便利之處在於,負責在特定展位部署系統的人員在儲存庫中也有自己的專用空間來儲存他們的文件。 同時,如果憑證由另一個系統提供,仍然可以指定伺服器上憑證的絕對路徑。

一個環境中的多個展位

通常需要在同一環境中部署幾個幾乎相同的展位,且差異極小。 在這種情況下,我們將環境相關變數分為在該環境內不發生變化的變數和發生變化的變數。 我們將後者直接轉移到庫存文件本身。 經過此操作後,可以直接在環境目錄中建立另一個清單。

它將重複使用 group_vars 庫存,並且還能夠直接為自己重新定義一些變數。

部署專案的最終目錄結構:

mydeploy                        # Каталог деплоя
├── deploy.yml                  # Плейбук деплоя
├── files                       # Каталог для файлов деплоя
│   ├── prod                    # Католог для средозависимых файлов стенда prod
│   │   └── certs               # 
│   │       └── myapi.key       #
│   └── test1                   # Каталог для средозависимых файлов стенда test1
├── group_vars                  # Каталог переменных плейбука
│   ├── all.yml                 # Файл для переменных связи всей системы
│   ├── myapi.yml               # Файл переменных свойств группы myapi
│   ├── bbauth.yml              # 
│   └── ghauth.yml              #
└── inventories                 #
    ├── prod                    # Каталог окружения prod
    │   ├── group_vars          # Каталог для переменных инвентори
    │   │   ├── myapi           #
    │   │   │   ├── vars.yml    # Средозависимые переменные группы myapi
    │   │   │   └── vault.yml   # Секреты (всегда средозависимы)
    │   │   ├── bbauth          # 
    │   │   │   ├── vars.yml    #
    │   │   │   └── vault.yml   #
    │   │   └── ghauth          #
    │   │       ├── vars.yml    #
    │   │       └── vault.yml   #
    │   └── prod.ini            # Инвентори стенда prod
    └── test                    # Каталог окружения test
        ├── group_vars          #
        │   ├── myapi           #
        │   │   ├── vars.yml    #
        │   │   └── vault.yml   #
        │   ├── bbauth          #
        │   │   ├── vars.yml    #
        │   │   └── vault.yml   #
        │   └── ghauth          #
        │       ├── vars.yml    #
        │       └── vault.yml   #
        ├── test1.ini           # Инвентори стенда test1 в среде test
        └── test2.ini           # Инвентори стенда test2 в среде test

加起來

依照文章組織變數後:每個變數檔案負責一個特定的任務。 由於文件具有某些任務,因此可以指派專人負責每個文件的正確性。 例如,系統部署的開發人員負責正確填寫劇本變量,而在清單中描述立場的管理員則直接負責填寫變數清單。

角色成為具有自己介面的自己的開發單元,允許角色開發人員開發功能而不是根據系統自訂角色。 這個問題尤其涉及戰役中所有系統的共同角色。

系統管理員不再需要了解部署程式碼。 成功部署所需要做的就是填寫環境相關變數的文件。

文學

  1. Документация

作者

卡柳日內·丹尼斯·亞歷山德羅維奇

來源: www.habr.com

添加評論