美文网首页
自动化运维工具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