Author: 本末丶
前言
我们通过Ansible去初始化一个集群配置时,通常会遇到需要给主机分配不通的ID或者标记主机角色,决定哪些是master(manager),哪些是slave(worker),常规的做法是在inventory中或者host_vars下定义好ID或者角色,如:
[cluster] node01 ansible_host=10.18.1.190 id=1 role=master node02 ansible_host=10.18.1.191 id=2 role=slave node03 ansible_host=10.18.1.192 id=3 role=slave node04 ansible_host=10.18.1.193 id=4 role=slave node05 ansible_host=10.18.1.194 id=5 role=slave
但这种办法并不是十分方便,每次要去修改配置。这里我们借助jinja2和一些判断方法,自动给集群主机分配ID跟role
为集群主机分配ID
inventory如下所示
[cluster] node01 ansible_host=10.18.1.190 node02 ansible_host=10.18.1.191 node03 ansible_host=10.18.1.192 node04 ansible_host=10.18.1.193 node05 ansible_host=10.18.1.194
分配ID只需要一条task
---
- hosts: cluster
gather_facts: false
tasks:
# ansible_play_hosts_all是当前执行的所有主机列表,类型为有序list,
# inventory_hostname为各自执行主机的名字
# 即:在list中找出各自名字的索引做为ID值
- set_fact: id={{ ansible_play_hosts_all.index(inventory_hostname) }}
# 使用id时候请转换成整型,set_fact不会帮你转换数据类型
- debug: msg="{{ inventory_hostname }} --> ID --> {{ id | int }}"执行结果
# ansible-playbook test.yml
PLAY [cluster] **********************************************************************
TASK [set the facts] ****************************************************************
... ...
TASK [debug] ************************************************************************
ok: [node01] => {
"msg": "node01 --> ID --> 0"
}
ok: [node02] => {
"msg": "node02 --> ID --> 1"
}
ok: [node03] => {
"msg": "node03 --> ID --> 2"
}
ok: [node04] => {
"msg": "node04 --> ID --> 3"
}
ok: [node05] => {
"msg": "node05 --> ID --> 4"
}
PLAY RECAP **************************************************************************
... ...可能有人问,我想递增差10呢?其实很容易
# jinja2可以直接计算
- set_fact: id={{ ansible_play_hosts_all.index(inventory_hostname) * 10 }}获取我想获取一个差值为5,递减的权重值呢?
# jinja2可以直接计算
- set_fact: id={{ 100 - ansible_play_hosts_all.index(inventory_hostname) * 5 }}... ...
其实通过index()获取的只是一个基数,只要通过合适的数学计算,一般都能得到你想要的结果(其他计算方法参考jinja2 math filter)。
为集群主机分配角色
通过上面的方法我们可以获取一组ID,同样的,我们也可以通过类似的方法为集群主机分配角色。
---
- hosts: cluster
gather_facts: false
tasks:
# 这里为了更好的展示,使用了>换行语句
# 即,索引ID为0的作为mater,其他都为slave
- set_fact:
role: >-
{%- if ansible_play_hosts_all.index(inventory_hostname) == 0 -%}
master
{%- else -%}
slave
{%- endif -%}
- debug: msg="{{ inventory_hostname }} --> role --> {{ role }}"执行结果:
# ansible-playbook test.yml
PLAY [cluster] ***********************************************************************
TASK [set_fact] **********************************************************************
... ...
TASK [debug] *************************************************************************
ok: [node01] => {
"msg": "node01 --> role --> master"
}
ok: [node02] => {
"msg": "node02 --> role --> slave"
}
ok: [node03] => {
"msg": "node03 --> role --> slave"
}
ok: [node04] => {
"msg": "node04 --> role --> slave"
}
ok: [node05] => {
"msg": "node05 --> role --> slave"
}
PLAY RECAP ***************************************************************************
... ...在集群环境中,我们可能需要不止一个master,改动如下
---
- hosts: cluster
gather_facts: false
tasks:
# 这里为了更好的展示,使用了>换行语句
- set_fact:
role: >-
{# 即,索引ID小于3的都分配为master #}
{%- if ansible_play_hosts_all.index(inventory_hostname) < 3 -%}
master
{%- else -%}
slave
{%- endif -%}
- debug: msg="{{ inventory_hostname }} --> role --> {{ role }}"执行结果:
# 如果>标记没有-,会出现换行
# ansible-playbook test.yml
PLAY [cluster] ***********************************************************************
TASK [set_fact] **********************************************************************
... ...
TASK [debug] *************************************************************************
ok: [node01] => {
"msg": "node01 --> role --> master"
}
ok: [node02] => {
"msg": "node02 --> role --> master"
}
ok: [node03] => {
"msg": "node03 --> role --> master"
}
ok: [node04] => {
"msg": "node04 --> role --> slave"
}
ok: [node05] => {
"msg": "node05 --> role --> slave"
}
PLAY RECAP **************************************************************************
... ...
我想即分配id,又分配角色呢?其实,也很简单。
---
- hosts: cluster
gather_facts: false
tasks:
- set_fact: id={{ ansible_play_hosts_all.index(inventory_hostname) }}
# id小于3的都视为master,记得要转换为整形,set_fact不会帮你处理数据类型
# PS: 这里用了python的小技巧,用jinja2的if去判断也是一样的
- set_fact:
role: "{{ ['slave','master'][id|int<3] }}"
- debug: msg="ID--> {{ id | int }}, role --> {{ role }}"结果:
# ansible-playbook test.yml
PLAY [cluster] ***********************************************************************
TASK [set_fact] **********************************************************************
ok: [node01]
ok: [node02]
ok: [node03]
ok: [node04]
ok: [node05]
TASK [set_fact] **********************************************************************
ok: [node01]
ok: [node02]
ok: [node03]
ok: [node04]
ok: [node05]
TASK [debug] *************************************************************************
ok: [node01] => {
"msg": "ID--> 0, role --> master"
}
ok: [node02] => {
"msg": "ID--> 1, role --> master"
}
ok: [node03] => {
"msg": "ID--> 2, role --> master"
}
ok: [node04] => {
"msg": "ID--> 3, role --> slave"
}
ok: [node05] => {
"msg": "ID--> 4, role --> slave"
}
PLAY RECAP ***************************************************************************
node01 : ok=3 changed=0 unreachable=0 failed=0
node02 : ok=3 changed=0 unreachable=0 failed=0
node03 : ok=3 changed=0 unreachable=0 failed=0
node04 : ok=3 changed=0 unreachable=0 failed=0
node05 : ok=3 changed=0 unreachable=0 failed=0 其他用处:
比如,有童鞋想给一组机器分配主机名wh-hadoop-[0~n].abc.cn,其中[0~n]按照IP或者主机名顺序从0开始递增,代码如下:
---
- hosts: cluster
gather_facts: false
tasks:
- debug: msg="wh-hadoop-{{ ansible_play_hosts_all.index(inventory_hostname) }}.abc.cn"
# debug不是必须的,我这里为了展示注释了hostname模块,
# - hostname: name=wh-hadoop-{{ ansible_play_hosts_all.index(inventory_hostname) }}.abc.cn执行:
# ansible-playbook test.yml -k
SSH password:
PLAY [cluster] ***********************************************************************
TASK [set_fact] **********************************************************************
ok: [node01]
ok: [node03]
ok: [node05]
ok: [node04]
ok: [node02]
TASK [debug] *************************************************************************
ok: [node01] => {
"msg": "wh-hadoop-0.abc.cn"
}
ok: [node03] => {
"msg": "wh-hadoop-2.abc.cn"
}
ok: [node05] => {
"msg": "wh-hadoop-4.abc.cn"
}
ok: [node04] => {
"msg": "wh-hadoop-3.abc.cn"
}
ok: [node02] => {
"msg": "wh-hadoop-1.abc.cn"
}
PLAY RECAP ************************************************************************
node01 : ok=2 changed=0 unreachable=0 failed=0
node02 : ok=2 changed=0 unreachable=0 failed=0
node03 : ok=2 changed=0 unreachable=0 failed=0
node04 : ok=2 changed=0 unreachable=0 failed=0
node05 : ok=2 changed=0 unreachable=0 failed=0
注意:,请将ansible_play_hosts_all替换成ansible_play_hosts是因为如果设置了serial,主机列表会被拆分掉,拿到的索引会不对。
emm... 编不下去了。。不写了。。。
没有帐号? 立即注册