美文网首页
自动化运维工具ansible使用入门(视频和演示源码)

自动化运维工具ansible使用入门(视频和演示源码)

作者: 赚钱笔记 | 来源:发表于2018-11-30 12:29 被阅读0次

作者:李佶澳     转载请保留:原文地址     发布时间:2018/03/12 15:43:00

说明

8元小课

一句话原理

文档介绍

下载素材

两个命令: ansible 与 ansible-playbook

用ansible命令操作目标机器

准备hosts文件

使用modules开始操作

用ansible-playbook命令操作目标机器

在目标机器上创建一个文件

将操作以role为单位进行分组

常用的目标机器初始化操作

设置免密码登录

设置目标机器的hostname

设置目标机器的时区

用yum安装依赖包

用systemd启动服务

变量、文件、模版与Handler

变量的定义和引用

模版上传

文件上传

handler的触发

参考

说明

ansible是一个常用的运维管理工具,使用它可以避免很多重复性工作,节省大量时间。

这里是网易云课堂·IT技术快速入门学院演示视频中使用的文档,8元小课系列,可以在系列教程中找到该系列所有文章。

QQ交流群(ansible实践互助):955105412。

8元小课

之前尝试制作了两期《HyperLedger Fabric》的课程,得到不少了同学的捧场。同时发现一些技术工具和学习方法,对我们这些工作了好多年的老鸟来说,早已习以为常,但是对于部分还在学校的或刚毕业的同学来说,非常陌生。

这些内容本质上又非常简单,只有“知道”与“不知道”这样一点点区别,不值得长篇大论,但结果却是没有人来点破,或者被包裹进昂贵的课程中,不可思议的价格,给在校生带来经济上的压力。

我们认为,把这些内容用“小课”的方式呈现出来,是很有价值的。一门小课,就像是公司内部的一次小小的分享会,可以把一个人的劳动所得复制给更多人,从而为听众节省大量的时间。

一句话原理

ansible就是把你手动ssh登录到多个目标机器上进行的一系列操作的过程自动化。

你只需要确保执行ansible命令的本地机器能够通过用户名和密码登录到目标机器上,并且在本地机器上的ansible文件中写好要在目标机器上执行的操作。

目标机器只需要支持ssh登录和python命令(一般的linux操作系统都有,ansible会将python写的任务脚本上传到目标机器上执行)。

文档介绍

ansible的文档首页 https://docs.ansible.com/ 对文档进行了分类,都是接到了文档内容页面

安装文档中介绍了ansible的安装方法,作为一个很基础的工具,基本上每个操作系统,都有对应的安装方法。

官方的Getting Started介绍的太简单了,对初学者来说,看完还是一头雾水。

下载素材

git clone https://github.com/lijiaocn/ansible-example.git

两个命令: ansible 与 ansible-playbook

ansible有两个命令,一个是ansible,一个是ansible-playbook,前者需要每次输入要执行的命令,后者可以读取playbook文件,一次性完成playbook文件中指定一系列操作。

playbook文件是重点,文档中有很大篇幅是介绍playbook的:playbook

用ansible命令操作目标机器

准备hosts文件

需要准备一个文件,在文件中写下目标机器的地址,这个文件默认是/etc/ansible/hosts,但是为了管理方便,最好为每个环境单独创建一个hosts文件。

比方说创建一个名为inventories的目录,在这个目录下,为生产环境的机器创建一个production目录,production/hosts中记录的是生产环境中的机器的地址,demo/hosts中记录的是演示环境中机器的地址,这样将不同环境中的机器明确地分开了,可以减少运维事故。

$ tree inventories/

inventories/

├── production

│   └── hosts

└── demo

    └── hosts

hosts文件中可以直接是目标机器的地址,可以是IP,也可以是域名,每个地址占用一行,例如:

192.168.33.11

www.baidu.com

如果目标集群中的机器的角色相同,承担的是同样任务,这种方式一般也足够了。如果目标集群中的机器分别承担不同任务,最好将它们按照各自的角色分组,例如:

[master]192.168.33.11[nodes]192.168.33.11192.168.33.12192.168.33.13

同一个地址,可以同时位于多个组中。

可以对分组再次分组,例如《Kubernetes1.12从零开始》中使用的hosts文件是这样的:

[etcd]192.168.33.11192.168.33.12192.168.33.13[master]192.168.33.11192.168.33.12192.168.33.13[node]192.168.33.11192.168.33.12192.168.33.13[kube-router]192.168.33.11192.168.33.12192.168.33.13#############  group's group  ##############[etcd_client:children]etcdmaster[etcd_server:children]etcd[etcd_peer:children]etcd[apiserver:children]master[controller:children]master[scheduler:children]master[kubelet_client:children]master[kubelet:children]node

名称里有:children的分组,是分组的分组,它的成员是前面定义的分组。

还可以在这里为每个机器设置变量,譬如《HyperLedger Fabric手把手入门》中使用的hosts文件:

[orderer]orderer0.member1.example.comMSPID=orderers.member1.example.comORG_DOMAIN=member1.example.comansible_host=192.168.33.11[peer]peer0.member1.example.comMSPID=peers.member1.example.comORG_DOMAIN=member1.example.comansible_host=192.168.33.11STATE_DB=CouchDBCOUCH_USER=adminCOUCH_PASS=passwordpeer1.member1.example.comMSPID=peers.member1.example.comORG_DOMAIN=member1.example.comansible_host=192.168.33.12STATE_DB=CouchDBCOUCH_USER=adminCOUCH_PASS=passwordpeer0.member2.example.comMSPID=peers.member2.example.comORG_DOMAIN=member2.example.comansible_host=192.168.33.13STATE_DB=CouchDBCOUCH_USER=adminCOUCH_PASS=password[machine]192.168.33.11192.168.33.12192.168.33.13

你已经注意到了,这个hosts文件不太一样,地址后面多出了一些诸如MSPID=XXX样式的内容,它们是为对应机器设置的变量,这些变量在可以在后面要讲的playbook文件中引用。

分组和变量的使用方法在后面演示,现在你先记得有这么一回事就行。

另外关于分组还要多说一句,ansible有两个默认的分组:all和ungrouped:all分组包括所有分组的中的机器,ungrouped是所有只属于all分组,不属于其它分组的机器。在定义你自己的分组的时候,要注意分组名称不要与它们冲突。

讲述这部分内容的官方文档是:Working with Inventory

使用modules开始操作

Modules是ansible的“军火库”,几乎所有的操作功能都是用module实现的。

ansible用到最后,就是在使用module。

module的数量相当多,好在常用的就那么几个,这里演示一些常用的,其它的你可以通过每个module的文档学习。

ping模块是用来测试目标机器是否可达的,用法如下:

lijiaos-mbp:example lijiao$ ansible-iinventories/demo/hosts-uroot-kall-mpingSSH password:192.168.33.12 | SUCCESS=>{"changed":false,"ping":"pong"}192.168.33.11 | SUCCESS=>{"changed":false,"ping":"pong"}

-i指定hosts文件,-u指定目标机器上的用户名,-k指定目标机器登录密码,all是要操作的hosts文件中的分组,前面我们说过,all是默认存在的一个分组,包括所有机器,-m指定要使用的模块ping。

ping模块大概是最简单的一个模块,没有参数,再来看一个复杂一点的模块shell,它的功能是在目标机器上执行shell命令:

lijiaos-mbp:example lijiao$ ansible-iinventories/demo/hosts-uroot-kall-mshell-a"hostname"SSH password:192.168.33.11 | SUCCESS |rc=0>>192.168.33.11192.168.33.12 | SUCCESS |rc=0>>192.168.33.12

-a是指定传递给模块的参数。

用ansible命令对目标机器操作时,都是在命令行指定要做的操作,一般都是一些比较简单操作,譬如查看下状态、上传下载文件等。

很多强大的功能要通过ansible-playbook才能发挥出来。

用ansible-playbook命令操作目标机器

playbooks是yml格式的文件,描述了要在哪些机器上执行哪些操作。

在目标机器上创建一个文件

创建一个playbook文件,playbook-single.yml,如下:

-hosts:machinesremote_user:roottasks:-name:create a tmp fileshell:|cd /tmp/touch abcd123

这个playbook文件的意思是,在所有的machines上,用root的身份执行,并通过shell模块创建文件/tmp/abcd123,用法如下:

lijiaos-mbp:example lijiao$ ansible-playbook-iinventories/demo/hosts-kplaybook-single.ymlSSH password:PLAY[machines]******************************************************************************TASK[Gathering Facts]***********************************************************************ok:[192.168.33.12]ok:[192.168.33.11]TASK[create a tmp file]*********************************************************************changed:[192.168.33.12]changed:[192.168.33.11]PLAY RECAP***********************************************************************************192.168.33.11              :ok=2changed=1unreachable=0failed=0192.168.33.12              :ok=2changed=1unreachable=0failed=0

注意这里使用ansible-playbook命令,-i和-k参数含义与前面ansible命令的参数相同,这里没有使用-u指定账号,是因为在playbook-single.yml中已经设置了使用root:

remote_user: root

操作在playbook文件的tasks中设置,tasks是一个数组,可以添加多个任务:

  tasks:

  - name: create a tmp file      # 自定义的操作名称

    shell: |                    # 使用shell模块,后面的|是yaml语法,表示后面空行之前的内容都是shell模块的参数

      cd /tmp/

      touch abcd123

用ansible命令来看一下文件是否创建:

lijiaos-mbp:example lijiao$ ansible-iinventories/demo/hosts-uroot-kall-mshell-a"ls /tmp/abc*"SSH password:192.168.33.11 | SUCCESS |rc=0>>/tmp/abcd123192.168.33.12 | SUCCESS |rc=0>>/tmp/abcd123

将操作以role为单位进行分组

前面给出的ansible-playbook的用法,是最初级的用法,比较完整的用法是将操作封装到role中。

先解释一下什么是role,为什么要有role。

在ansible看来role就是对playbook中的操作做了一次分组,把一些操作放在这个role中,另一些操作放在那个role中。

在我们看来,role是目标机器的角色之一,我们把不同的角色的操作划分到不同的目录中,一是管理方便,二是可以复用。

role要在roles目录中定义,在roles目录中创建与role同名的目录,每个role目录中包含四个目录:

lijiaos-mbp:example lijiao$ tree roles/roles/└── prepare    ├── files    │   └── demo.file    ├── handlers    │   └── main.yml    │   └── centos.yml    ├── tasks    │   └── main.yml    └── templates        └── demo.template.j2

tasks目录中的main.yml是这个role的操作入口,handlers/main.yml中是一些可以被触发的操作,files中存放可以直接被上传到目标机器的文件,templates中存放的是可以直接上传到目标机器的模版文件,这两个的区别后面说明。

注意tasks/main.yml是必须要有的,其它目录中如果没有文件,可以不创建。

上面的目录中创建了一个名为prepare的role,我们计划将机器的初始化设置操作全部在收集在这个role中,task/main.yml是这样写的:

- name: Set authorized key

  tags: ssh

  authorized_key:

      user: root

      key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"

- name: Set hostname

  hostname:

    name: "{{ inventory_hostname }}"

- name: Set bash prompt

  shell: |

      echo 'export PS1="[\u@\H \W]\\$ "'>> ~/.bashrc

- name: install dependent packages

  import_tasks: centos.yml

  when: ansible_distribution == "CentOS"

用到了authorized_keyhostnameshellimport_tasks四个模块。

当目标机器的操作系统是ansible的时候,import_tasks引入了centos.yml文件:

- name: set time zone

  file:

    src: '{{ item.src }}'

    dest: '{{ item.dest }}'

    state: link

  with_items:

    - { src: "/usr/share/zoneinfo/Asia/Shanghai", dest: "/etc/localtime" }

- name: set local

  shell: localedef -i zh_CN  -f UTF-8 zh_CN.UTF-8

- name: install epel

  yum:

    name: "{{ item }}"

    state: present

  with_items:

    - epel-release

- name: install pkgs

  yum:

    name: "{{ item }}"

    state: present

  with_items:

    - yum-utils

    - ipset

    - iptables

    - iproute

    - ipvsadm

    - supervisor

    - ntp 

- name: start basic service

  systemd:

    enabled: yes

    name: "{{ item }}"

    state: started

  with_items:

    - ntpd

    - supervisord

这些操作的含义在后面章节逐一说明,先给出用法:

ansible-playbook -i inventories/demo/hosts  -u root -k prepare.yml

常用的目标机器初始化操作

这里介绍role/prepare/task/main.yml文件中的操作。

设置免密码登录

前面的操作过程中使用了-k参数,每次都需要输入密码,一是比较烦,二是如果机器的密码不同,那就失灵了(后面会演示一下如果目标机器密码不同该怎样操作)。

最好把本地的证书传到目标机器上,实现免密码登录,prepare的task/main.yml中,有这样一段:

- name: Set authorized key

  tags: ssh

  authorized_key:

      user: root

      key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"

它就是用authorized_key模块将本地的证书~/.ssh/id_rsa.pub上传到目标机器上,实现免密码登录。

注意你需要确保你本地有id_rsa.pub文件,否则用ssh-keygen命令创建一个:

$ ssh-keygen

Generating public/private rsa key pair.

Enter file in which to save the key (/Users/lijiao/.ssh/id_rsa):

设置目标机器的hostname

- name: Set hostname

  hostname:

    name: "{{ inventory_hostname }}"

- name: Set bash prompt

  shell: |

      echo 'export PS1="[\u@\H \W]\\$ "'>> ~/.bashrc

设置目标机器的时区

- name: set time zone

  file:

    src: '{{ item.src }}'

    dest: '{{ item.dest }}'

    state: link

  with_items:

    - { src: "/usr/share/zoneinfo/Asia/Shanghai", dest: "/etc/localtime" }

用yum安装依赖包

- name: install epel

  yum:

    name: "{{ item }}"

    state: present

  with_items:

    - epel-release

- name: install pkgs

  yum:

    name: "{{ item }}"

    state: present

  with_items:

    - yum-utils

    - ipset

    - iptables

    - iproute

    - ipvsadm

    - supervisor

    - ntp 

用systemd启动服务

- name: start basic service

  systemd:

    enabled: yes

    name: "{{ item }}"

    state: started

  with_items:

    - ntpd

    - supervisord

变量、文件、模版与Handler

这里通过在目标机器上部署、设置nginx,讲解角色下面的files、templates和handlers目录的作用。

nginxrole的文件如下:

lijiaos-mbp:example lijiao$ tree roles/nginx/roles/nginx/├── files│   ├── start.sh│   └── stop.sh├── handlers│   └── main.yml├── tasks│   └── main.yml└── templates    └── hello.com.conf.j2

变量的定义和引用

nginx/tasks/main.yml内容是:

- name: install pkgs

  yum:

    name: "{{ item }}"

    state: present

  with_items:

    - nginx

- name: nginx is running

  systemd:

    name: nginx

    state: started

    daemon_reload: yes

- name: create directory

  file:

    path: "{{ item }}"

    state: directory

  with_items:

    - "{{ nginx_config_path }}"

    - "{{ nginx_script_path }}"

- name: upload template config

  notify: reload nginx

  template:

    src: "{{ item }}.j2"     

    dest: "{{ nginx_config_path }}/{{ item }}"

  with_items:

  - hello.com.conf

- name: upload files

  copy:

    src: "{{ item }}"

    dest: "{{ nginx_script_path }}/{{ item }}"

    mode: u=rwx

  with_items:

  - start.sh

  - stop.sh

这里有两个变量:nginx_config_path和nginx_script_path,用两个大括号包裹引用。

它们是在inventories/demo/group_vars/all中定义的:

nginx_config_path:  /etc/nginx/conf.d

nginx_script_path: /root/nginx

变量除了可以在group_vars和host_vars目录中定义,还可以在hosts文件中定义:

[machines]

192.168.33.11 port=8001

192.168.33.12 port=8002

以及在playbook文件中定义,回想一下我们用到的第一个playbook,里面有vars:

$ cat playbook-single.yml- hosts: machines  vars:    http_port: 80    max_clients: 200  remote_user: root  tasks:  - name: create a tmp file    shell: |cd/tmp/      touch abcd123

模版上传

role/nginx/templates/hello.com.conf.j2是一个模版文件:,模版文件中可以使用变量:

server {

listen {{ port }};

location / {

proxy_pass https://www.baidu.com ;

}

}

模版文件中可以使用变量,这里使用的变量port是在hosts文件中定义的,可以为每个机器定义不同的端口:

[machines]

192.168.33.11 port=8001

192.168.33.12 port=8002

它们被用template模块上传,上传时会将模版文件中的变量换成变量的值,如下:

- name: upload template config

  notify: reload nginx

  template:

    src: "{{ item }}.j2"     

    dest: "{{ nginx_config_path }}/{{ item }}"

  with_items:

  - hello.com.conf

文件上传

role/nginx/files中的文件,用COPY命令上传,文件不会被做任何改动,这一点和templates显著不同:

- name: upload files

  copy:

    src: "{{ item }}"

    dest: "{{ nginx_script_path }}/{{ item }}"

    mode: u=rwx

  with_items:

  - start.sh

  - stop.sh

handler的触发

在tasks中,用notify命令触发handler的执行:

- name: upload template config

  notify: reload nginx

  template:

    src: "{{ item }}.j2"     

    dest: "{{ nginx_config_path }}/{{ item }}"

  with_items:

  - hello.com.conf

只有被触发的handler才会运行,并且是在所有的task之后运行。

如果有多个handler被触发,按照它们在handlers/main.yml中出现的顺序执行。

什么时候要用handler?

譬如说,配置文件被更新以后,需要重启或者重新加载的服务,这时候就可以在更新配置文件的task中,使用notify触发handler。

参考

ansible documents

ansible Dynamic Inventory

ansible playbook Best Practices

ansible Delegation, Rolling Updates, and Local Actions

ansible Jinja2 templating

ansible all modules

how to access host variable of a different host with Ansible?

Ansible Loops

Ansible Conditionals

ansible special variables

相关文章

网友评论

      本文标题:自动化运维工具ansible使用入门(视频和演示源码)

      本文链接:https://www.haomeiwen.com/subject/wozccqtx.html