iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 28
0
Kubernetes

在地端建置Angular+ASP.NET Core的DevOps環境系列 第 28

day28_ansible06_variables_with_dict,group_vars,vars_files

前言

今天的主題:variables
嗯…繼續把他看下去(鳴鳴,星期一)

其實在網路找的專案,我常常找不到某個變數是哪邊生出來的
可能要靠debug印出來看看吧?
有更好的方式嗎?

with_dict

https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#looping-over-hashes
以RDBMS的術語來看
多個rows(items),有loop的效果(for...each items),每1個row(key),又能有很多colume(value),的感覺
好東西不用嗎?

範例一

- name: with_dict
  debug:
    msg: "{{ item.key }} - {{ item.value }}"
  with_dict: "{{ dictionary }}"

- name: with_dict -> loop (option 1)
  debug:
    msg: "{{ item.key }} - {{ item.value }}"
  loop: "{{ dictionary|dict2items }}" # 可以轉成items

- name: with_dict -> loop (option 2)
  debug:
    msg: "{{ item.0 }} - {{ item.1 }}"
  loop: "{{ dictionary|dictsort }}" # 可以對dict排序一下

範例二

參考
https://github.com/paulramsey/ansible

  • /defaults/main.yml

我們把with_dict的變數放在這,這個role都能叫用的到

---
sites:
  myapp1: # key1
    frontend: 80 # value1 # {{ item.value.frontend }}
    backend: 80 # value1 # {{ item.value.backend }}
  myapp2: # key2
    frontend: 80 # value2
    backend: 80 # value2

樣板

  • /templates/nginx.conf.j2
upstream {{ item.key }} {
{% for server in groups.webserver %}
    server {{ server }}:{{ item.value.backend }};
{% endfor %}
}

server {
    listen {{ item.value.frontend }}; # 沒用with_dict前長這樣 listen 80;

    location / {
        proxy_pass http://{{ item.key }};
    }
}
# ====
# 本來長這樣
upstream demo {{% for server in groups.webserver %}    server {{ server }};{% endfor %}}
server {    listen 80;
    location / {        proxy_pass http://demo;    }}

主角with_dict上場囉

- name: activate nginx sites
  file: src=/etc/nginx/sites-available/{{ item.key }} dest=/etc/nginx/sites-enabled/{{ item.key }} state=link
  with_dict: sites

- name: configure nginx sites
  template: src=nginx.conf.j2 dest=/etc/nginx/sites-available/{{ item.key }} mode=0644 # 把j2的template copy到dest
  with_dict: sites # 有loop的效果,一個row,又能有很多colume,的感覺

===

把「variable環境變數」跟「playbook」分離
-環境變數可能比較機密
-一個設計很好的playbook,統一在改環境變數,就能適用在各種環境了
-playbook進版控,環境變數清空,或留預設值供參考

Working with Inventory

https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#splitting-out-host-and-group-specific-data

  • Hosts and Groups
  • Host Variables
  • Group Variables
  • Groups of Groups, and Group Variables
  • Default groups
  • Splitting Out Host and Group Specific Data
  • How Variables Are Merged
  • List of Behavioral Inventory Parameters
  • Non-SSH connection types
    這些主題很重要,個人也有難看不懂,所以建議大家看原文
    這裡試著筆記一些部分

Hosts and Groups

主機清單
可能在/inevntory/hosts.ini
可以寫成ini格式(好像看到專案的都寫ini)

mail.example.com # 你的hosts都有dns的

[webservers]
foo.example.com
bar.example.com
www[01:50].example.com # 也可以用簡單的語言,表示:www01~www50
www-[a:f].example.com # 英文字麻a通!!

[dbservers]
one.example.com
two.example.com
three.example.com
  • 也可以寫成yaml檔
all:
  hosts:
    mail.example.com:
  children:
    webservers:
      hosts:
        foo.example.com:
        bar.example.com:
    dbservers:
      hosts:
        one.example.com:
        two.example.com:
        three.example.com:

在家裡的環境,大部分沒domain name,就是給主機別名aliases,再給static ip
(不要吃dhcp,不然你dhcp要固定這些hosts的mac配給固定ip)

  • ini
jumper(別名) ansible_port=5555 ansible_host=192.0.2.50 \
             ansible_connection=ssh        ansible_user=mpdehaan
  • yaml
...
  hosts:
    jumper:
      ansible_port: 5555
      ansible_host: 192.0.2.50

Host Variables

  • 直接寫在inventory裡面(很low)
[atlanta]
host1 http_port=80 maxRequestsPerChild=808 
host2 http_port=303 maxRequestsPerChild=909

Group Variables

The INI way:
[atlanta] # 這個group的主機
host1
host2

[atlanta:vars] # group atlanta的變數
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
The YAML version:
atlanta:
  hosts:
    host1:
    host2:
  vars:
    ntp_server: ntp.atlanta.example.com
    proxy: proxy.atlanta.example.com

Groups of Groups, and Group Variables

這個也蠻常見的,不難,一定要會
要注意:

Groups of Groups

  • ini格式的冒號「 :」在前面 => :children
  • yaml格式的冒號「 :」在後面 => children:

Group Variables

yaml格式的冒號「 :」前、後都能放 => :vars、vars:
解決方式:

  • 1、統一用ini格式
  • 2、yaml檔的冒號統一放後面,避免confused
[atlanta]
host1
host2

[raleigh]
host2
host3
# southeast的小孩
[southeast:children] # groups的groups
atlanta
raleigh

[southeast:vars]
some_server=foo.southeast.example.com
halon_system_timeout=30
self_destruct_countdown=60
escape_pods=2
# usa的小孩
[usa:children]
southeast
northeast
southwest
northwest
# 所以階層就會長這樣
all: # 所有的hosts,永遠是最上層
  children:
    usa: # 此例中,usa輩份最年長,阿公了
      children:
        southeast: # 爸爸
          children:
            atlanta: # 兒子
              hosts:
                host1:
                host2:
            raleigh:
              hosts:
                host2:
                host3:
          vars: # southeast的變數,atlanta、raleigh都能用
            some_server: foo.southeast.example.com
            halon_system_timeout: 30
            self_destruct_countdown: 60
            escape_pods: 2
        northeast:
        northwest:
        southwest:

有一些原則:

  • 小孩如果有設變數,小孩的優先權是比較大的(蓋掉父親的變數)
  • group可以掛多個group(爸爸可以有很多阿公啦,可能同母異父吧…)
  • host可以掛好幾個group(兒子可以有很多爸爸,乾爹、乾媽)

Default group

all:所有的hosts
ungrouped:除了all以外,沒有group的主機

===

group_vars

比較偏一定會用到的、希望整個playbook都能用到的參數
這樣的變數會放在這些目錄底下

# 放在/etc/ansible
/etc/ansible/hosts
/etc/ansible/group_vars/raleigh # 各種格式都可以yml、yaml、json

# group raleigh的變數檔內容:
# ---
# ntp_server: acme.example.org # group raleigh的變數
# database_server: storage.example.org # group raleigh的變數

# 也可以group再建目錄(以group raleigh為例)
/etc/ansible/group_vars/raleigh/db_settings
/etc/ansible/group_vars/raleigh/cluster_settings

/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball
# 放在/ansible專案目錄/
/ansible專案目錄/group_vars/all/vars # 這個專案都能用的到的變數
/ansible專案目錄/inventory/group_vars/all.yml # 這些inventory(主機清單)都能用的到的變數

group_vars/和host_vars/可以存在於playbook/或inventory/中
如果兩個目錄都存在,則playbook/中的變數會蓋掉inventory/中的變數

然後再需要的地方引用

寫在script檔

#!/bin/bash
#
# Program: Vagrant func and vars
# History: 2017/1/19 Kyle.b Release # 參考K大的kube-ansible專案

GROUP_VARS_PATH="./inventory/group_vars/all.yml" 
# 變成GROUP_VARS_PATH,讓playbook使用{{GROUP_VARS_PATH}}
INVENTORY_PATH="./inventory/hosts.ini"
VAGRAN_CONFIG_PATH="./hack/.config.rb"

寫在.gitlab-ci.yml用在其他佈署情境(超過範圍,就不往下追了)

可能的情境

  • Virtualbox Deploy
  • Libvirt Deploy
  • OpenStack Deploy

===

vars_files

https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-file-separation
就是把variables寫在一個yaml檔
playbook有需要的時候再去吃它

  • /vars/external_vars.yml # 把變數寫在一個yaml檔
---
# in the above example, this would be vars/external_vars.yml
somevar: somevalue
password: magic
---
- hosts: all
  remote_user: root
  vars:
    favcolor: blue
  vars_files:
    - /vars/external_vars.yml # playbook需要的去叫用

  tasks:
  - name: this is just a placeholder
    command: /bin/echo foo

也可以在下ansible-playbook時給參數

如果你的ansible要更靈活的給第3方工具運用(例如你寫script、或其他自動化工具)

# key-value 格式
$ ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"

# JSON string format
$ ansible-playbook release.yml --extra-vars '{"version":"1.23.45","other_variable":"foo"}'
$ ansible-playbook arcade.yml --extra-vars '{"pacman":"mrs","ghosts":["inky","pinky","clyde","sue"]}'
# 要小心escaping quotes(所以下指令比較麻煩),不過還是有必須用到的情境
$ ansible-playbook arcade.yml --extra-vars "{\"name\":\"Conan O\'Brien\"}"
$ ansible-playbook arcade.yml --extra-vars '{"name":"Conan O'\\\''Brien"}'
$ ansible-playbook script.yml --extra-vars "{\"dialog\":\"He said \\\"I just can\'t get enough of those single and double-quotes"\!"\\\"\"}"

# YAML string format
$ ansible-playbook release.yml --extra-vars '
version: "1.23.45"
other_variable: foo'

$ ansible-playbook arcade.yml --extra-vars '
pacman: mrs
ghosts:
- inky
- pinky
- clyde
- sue'

# 把json或yaml格式的變數寫在一個檔案
$ ansible-playbook release.yml --extra-vars "@some_file.json"


上一篇
day27_ansible05_vault,variables_facts,defaults,vars
下一篇
day29_ansible07_其他_include,limit,tags,changed_when,failed_when,除錯
系列文
在地端建置Angular+ASP.NET Core的DevOps環境31

尚未有邦友留言

立即登入留言