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... 编不下去了。。不写了。。。
没有帐号? 立即注册