Z.S.K.'s Records

Ansible学习(ansible基础使用)

Ansible is a radically simple IT automation engine that automates cloud provisioning, configuration management, application deployment, intra-service orchestration, and many other IT needs.

Ansible is a radically simple IT automation engine that automates cloud provisioning, configuration management, application deployment, intra-service orchestration, and many other IT needs.

  • simple, based on python/jinja
  • no agent, based on ssh(default)
  • modular design
  • idempotency

工作架构

ansible只是一种框架, 真正执行任务是各种模块:

  • connection plugins:连接插件,负责和被监控端实现通信
  • host inventory:主机清单,是一个配置文件里面定义监控的主机
  • modules:ansible自身核心模块、自定义模块
  • Plugins:借助于插件完成记录日志邮件等功能
  • playbook:剧本执行多个任务

基本使用

在实际使用中, 为了安全一般不会直接在配置中使用明文, 都会提前配置好免密登录.

常用ansible的执行有以下两种方式(ansible-galaxy没用过,不讨论):

ad-hoc
1
ansible  [ -i  inventory文件 ]  分组名  -m  模块名  -a '模块参数'  ansible参数

官方模块列表

示例:

cat /etc/ansible/hosts

1
2
3
4
5
6
[all-machines]
172.16.104.210
172.16.104.211

[echo_date]
172.16.104.210

Hosts文件称之为host inventory文件, 该文件指定机器组别.

ansible -i /etc/ansible/hosts echo_date -m shell -a 'echo $(ifconfig|grep eth0)'

这里使用了免密登录, 所以可以直接执行, 如果没有免密登录的情况下, 可以在执行时输入密码(由于只能输入一次密码,这种情况要求所有机器上所使用的密码一致)或者直接在主机清单文件中直接指定用户名密码

1
2
3
k8snode-1 ansible_host=172.16.104.210 ansible_user=root ansible_ssh_pass='xxxx'
[echo_date]
k8snode-1
playbook

cat prepare.yaml

1
2
3
- hosts: echo_date
roles:
- { role: common }

ansible-playbook prepare.yml

playbook详见下文

Playbook/Role

Playbook及role是ansible为了实现更加复杂的编排任务及更好地组织对象而设定的抽象对象.

role主要将整个任务进行封装从而实现复用

playbook则明确定义要完成这个任务需要执行哪些步骤

一个role的标准目录

那么在其它有需要执行这个工作的地方则可以直接引用这个角色(或者角色中的部分步骤).

playbook则明确定义了完成这个role需要执行的tasks.

playbook的样例

cat roles/common/tasks/main.yml

1
2
3
4
5
6
7
8
9
---
- name: "make sure system:public-info-viewer cluster role manifests"
template:
src: "system-public-info-viewer-cluster-role.yml"
dest: "{{ kube_config_dir }}/kubernetes-api-system-public-info-viewer-cluster-role.yml"

- name: "enabled kubernetes api /version,/version/ auth"
shell: "{{ kubectl }} apply -f {{ kube_config_dir }}/kubernetes-api-system-public-info-viewer-cluster-role.yml"
...

两个大括号代表的是变量,在执行playbook前由jinja语法进行渲染, 执行时会被真正的value替换.

当然,playbook中配合各类module,可以实现更加复杂的逻辑

官方模块列表

var

ansible中的变量规则比较灵活, 允许我们在多处定义同一个变量, 再根据优先级决定执行时使用哪个变量.

常用的有以下几种定义变量方式(优先级从高到低):

  • set_fact/registry_vars
  • roles/vars/main.yml
  • group_vars/all.yaml
  • roles/defaults/main.yml

其它方式定义的变量优先级参考官方文档

tag

cat roles/common/tasks/main.yml

1
2
3
4
5
6
7
8
9
---
- name: "make sure system:public-info-viewer cluster role manifests"
template:
src: "system-public-info-viewer-cluster-role.yml"
dest: "{{ kube_config_dir }}/kubernetes-api-system-public-info-viewer-cluster-role.yml"

- name: "enabled kubernetes api /version,/version/ auth"
shell: "{{ kubectl }} apply -f {{ kube_config_dir }}/kubernetes-api-system-public-info-viewer-cluster-role.yml"
tag: enabled_kubernetes

进行引用时可以指定存在tag的是执行还是跳过

1
2
3
4
- hosts: kube-master[0]
roles:
- { role: common }
tags: enabled_kubernetes

ansible中内置4种tag: always、tagged、untagged、all 是四个系统内置的tag,有自己的特殊意义

  • always: 指定这个tag 后,task任务将永远被执行,除非明确使用–skip-tags always标记
  • tagged: 当 –tags 指定为它时,则只要有tags标记的task都将被执行
  • untagged: 当 –tags 指定为它时,则所有没有tag标记的task 将被执行
  • all: 这个标记无需指定,ansible-playbook 默认执行的时候就是这个标记.所有task都被执行

通过tag机制可以实现执行部分role功能.

template

cat roles/common/template/docker_auth.j2

1
2
3
4
5
6
7
{
"auths": {
"{{ docker_registry }}": {
"auth": "{{ docker_auth }}"
}
}
}

template通过jinja2语法进行渲染, 模块中的变量由参数传递过来, 参数var

templates机制可以让我们把共性的部分固定,将可变的部分由参数传递进模块,实现参数化.

执行机制

ansible执行分为同步和异步:

同步模式

也是默认值,按批执行, 即先在一批机器上(取决于fork的数量)执行playbook中第一个任务, 直到这批机器都执行完(默认配置下就算有机器提前执行完也需要等待所有机器都执行完这个任务)之后再在下一批机器执行第一个任务,待该任务在所有的机器上都执行完成之后,然后重新回到第一批机器开始执行playbook的下一个动作,依次循环

ansible2.0+可指定strategy=free 即可让提前完成的机器无需等待同批机器一同完成而快速地让下批机器执行.

默认情况下的playbook执行过程:

从这里也可以看出playbook中的task是所有机器都执行完之后再执行下一个task

异步模式

ansible直接将机器的任务(取决于fork的数量)放在后台执行, 并每隔一段时间去检查这些节点的执行完成情况(通过job-id),同样直到这批机器都执行完(就算有机器提前执行完也需要等待所有机器执行完),ansible才会将下一批机器放在后台执行. 异步通过async跟poll两个参数决定

同步跟异步的主要区别就是异步是通过轮询状态来判断任务是否执行成功的.

特殊地: 如果poll参数被指定为0, 则ansible在将机器的任务放在后台执行后立刻返回, 迅速地在下一批机器开始执行

也就是说ansible此时并不会管各机器的任务是否执行成功.

通过以上我们知道ansible默认是通过ssh远程登录执行的, 这个时间其实是受ssh的timeout控制, 如果任务的执行时间超过ssh的timeout时间, ssh会被断开, ansible会认为该任务失败.

因此, 我们可以直接将任务放到后台执行, 后续定时地去轮询任务执行完成与否. 这样即不受ssh Timeout限制.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---
host: all
#strategy: free/linear
max_fail_percentage: 30 #serial指定的节点个数中执行失败的host大于这个百分比,则终止这个任务.
serial: 5 #指定一次执行多少host
tasks:
- name: 'YUM - async task'
yum:
name: docker-io
state: present
async: 100 #参数值代表了这个任务执行时间的上限值。即任务执行所用时间如果超出这个时间,则认为任务失败
poll: 0 #任务异步执行时轮询的时间间隔,默认为10s,如果为0, 则表示不关心任务执行结果,只将任务推送到机器上执行,然后立即执行下一个任务
register: yum_sleeper

- name: 'YUM - check on async task'
async_status: #根据job_id获取任务执行状态
jid: "{{ yum_sleeper.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 30

--fork指定了同一时刻一个task能在多少个host上执行

--serial指定了同一时刻能够有多少个host执行完整个playbook(在strategy=free效果明显)

错误处理

正常情况下, playbook中的任何一个任务失败都将导致整个playbook终止运行, 我们可以使用ignore_errors: true来忽略这种场景, 即产生了错误也继续执行.

同时,也可使用fail/failed_when来捕获错误异常

1
2
3
4
5
6
7
8
9
10
11
12
---
- hosts: xxx
  remote_user: root
  tasks:
  - debug:
      msg: "I execute normally"
    ignore_errors: true
  - shell: "echo 'This is a string for testing error'"
    register: return_value #保留命令执行结果.
    failed_when: ' "error" in return_value.stdout'
  - debug:
      msg: "I never execute,Because the playbook has stopped"

最后的debug不会被执行.因为第2个task failed了.

参考文章:

转载请注明出处https://izsk.me

Z.S.K. wechat
Scan Me To Read on Phone
I know you won't do this,but what if you did?