benmo | 发布于 2018-08-21 10:25:25 | 阅读量 1148 | ? Ansible ?
发布于 2018-08-21 10:25:25 | ? Ansible ?

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... 编不下去了。。不写了。。。

 


内容更新于: 2019-08-02 09:47:27
链接地址: http://blog.leanote.com/post/benmo/ansible%E5%A6%82%E4%BD%95%E7%BB%99%E9%9B%86%E7%BE%A4%E4%B8%BB%E6%9C%BA%E8%87%AA%E5%8A%A8%E5%88%86%E9%85%8DID-%E8%A7%92%E8%89%B2%EF%BC%9F

上一篇: jenkins基于Ansible自动发布/回滚/管理spring boot/cloud一体化

下一篇: 从0开始使用shell编写一个ansible模块

1148 人读过
立即登录, 发表评论.
没有帐号? 立即注册
1 条评论
文档导航