zoukankan      html  css  js  c++  java
  • 02 . Ansible高级用法(运维开发篇)

    自动化任务简介

    假设我们要在10台linux服务器上安装一个nginx服务,手动是如何做的?

    # 第一步, ssh登录NUM(1,n)服务器
    # 第二步,输入对应服务器密码
    # 第三步,执行命令: yum install nginx 循环操作n=10
    # 第四步,执行命令: service nginx start
    # 第五步,退出登录
    

    自动化任务执行的意义

    # 意义一, 提升运维工作效率,减少一份工作成本
    # 意义二, 提高准确度.
    

    自动化任务执行的应用

    # 应用一, 批量命令执行
    # 应用二, 定时程序任务执行
    # 应用三, 批量程序应用服务安装
    # 应用四, 批量配置文件同步
    # 应用五, 批量代码部署
    

    ansible配置

    ansible是python中的一套模块,系统中的一套自动化工具,可以用作系统管理,自动化命令等任务

    ansible优势
    # 1.ansible是python中的一套完整的自动化执行任务模块
    # 2.ansible的play_book模式,不用yaml配置,对于自动化任务执行一目了然.
    # 3.自动化场景支持丰富
    
    ansible配置文件
    1. inventory
    # 该参数表示资源清单inventory文件的位置,资源清单就是一些Ansible需要连接管理的主机列表  
    # inventory = /root/ansible/hosts
    
    2. library
    # Ansible的操作动作,无论是本地或远程,都使用一小段代码来执行,这小段代码称为模块,这个library参数就是指向存放Ansible模块的目录  
    # library = /usr/share/ansible
    
    3. forks
    # 设置默认情况下Ansible最多能有多少个进程同时工作,默认设置最多5个进程并行处理。具体需要设置多少个,可以根据控制主机的性能和被管理节点的数量来确定。  
    # forks = 5
    
    4. sudo_user
    # 这是设置默认执行命令的用户,也可以在playbook中重新设置这个参数
    # sudo_user = root
    # 注意: 新版本已经做了修改,如ansible2.4.1下已经为:
    # default_sudo_user = root
    
    5. remote_port
    # 这是指定连接被关节点的管理端口,默认是22,除非设置了特殊的SSH端口,不然这个参数是不需要被修改的
    # remote_port = 22
    
    6. host_key_checking
    # 这是设置是否检查ssh主机的秘钥,可以设置为True或者False
    # host_key_checking = False
    
    7. timeout
    # 这是设置ssh连接的超时间隔,单位是秒
    # timeout = 20
    
    8. log_path
    # ansible系统默认是不记录日志的,如果想把ansible系统的输出记录到指定地方,需要设置log_path来指定一个存储Ansible日志的文件
    
    9. private_key_file
    # 在使用ssh公钥私钥登录系统时使用的秘钥路径
    # private_key_file=/path/to/file.pem
    
    ansible.cfg
    [defaults]
    inventory = /tmp/hosts
    forks = 5
    default_sudo_user = root
    remote_port = 22
    host_key_checking = Falsetimeout = 20
    log_path = /var/log/ansible.log
    #private_key_file=/tmp/file.pem
    

    ansible安装

    # 1. 通过系统的方式,yum,apt,get等
    # 2. 通过python的方式
    
    
    # (推荐)python ./setup.py install 
    easy_install ansible
    pip install ansible	
    

    Ansible基础操作

    当我们将Ansible安装好以后,可以通过一些命令开始深入了解Ansible了.
    我们最先展示的并非那强大的集配置,部署,自动化于一身的playbook.而是如何初始化.

    远程连接概述

    在我们开始前要先理解Ansible如何通过SSH与远程服务器连接是很重要的.
    Ansible1.3及之后的版本默认会在本地的OpenSSH可用时会尝试用其远程通讯,这会启用ControlPersist(一个性能特性),Kerberos,和在~/.ssh/config中的配置选项如 Jump Host setup.然而,当你使用Linux企业版6作为主控机(红帽企业版及其衍生版如CentOS),其OpenSSH版本可能过于老旧无法支持ControIPersist,在这些操作系统中,Ansible将会退回并采用paramiko(由Python实现的高质量OpenSSH库).如果你希望能够使用像是Kerberized SSH之类的特性,烦请考虑使用Fedora,OS X,或Ubuntu作为你的主控机直到相关平台上有更新版本的OpenSSH可供使用,或者启用Ansible的"accelerated mode".

    在Ansible1.2及之前的版本,默认将会使用paramiko,本地OpenSSH必须通过-c ssh或者配置文件中设定.

    我们偶尔会遇到不支持SFTP的设备,虽然很少见,但有概率中奖,可以通过ansible配置文件切换至scp模式来与之连接.

    说起远程设备,Ansible会默认假定你使用SSH key(当然也推荐这种)但是密码一样可以,通过在需要的地方添加-ask-pass选项来启用密码验证,如果使用了sudo特性,当sudo需要密码时,也同样适当的提供了-ask-sudo-pass选项.

    也许这是常识,但也值得分享:任何管理系统受益于被管理的机器在主控机附近运行.如果在云中运行,可以考虑在使用云中的一台机器来运行Ansible.

    作为一个进阶话题,Ansible不止支持SSH来远程连接.连接方式是插件化的而且还有许多本地化管理的选项诸如管理 chroot, lxc, 和 jail containers.一个叫做‘ansible-pull’的模式能够反转主控关系并使远程系统通过定期从中央git目录检出 并 拉取 配置指令来实现背景连接通信

    第一条命令(公钥认证)

    我们已经安装ansible了,第一件事就是编辑或者创建/etc/ansible/hosts并在其中加入一个或多个远程系统,我们的public SSH key必须在这些系统的authorized_keys中.

    # 我们现在ansible控制机上主机名解析
    tail /etc/hosts
    127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
    121.36.43.223	node1
    120.77.248.31	node2
    116.196.83.113	master
    
    # 将解析过的主机名放到ansible配置文件里面
    tail -2 /etc/ansible/hosts 
    node1
    node2
    
    # ansible控制机生成公钥并传给需要被控制的机器上
    ssh-copy-id node1
    ssh-copy-id node2
    # 因为考虑到安全问题,会有主机秘钥的检查,但如果在内网非常信任的服务器就没必要了.
    sed -i 's/# *StrictHostKeyChecking *ask/StrictHostKeyChecking no/g' /etc/ssh/ssh_config
    
    # 然后我们就可以执行第一条命令来查看能ping通控制的所有节点.
    ansible all -m ping
    node1 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }
    node2 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }
    

    Ansible会像SSH那样试图用你的当前用户名来连接你的远程机器.要覆写远程用户名,只需使用’-u’参数. 如果你想访问 sudo模式,这里也有标识(flags)来实现:

    ansible all -m ping -u bruce
    
    ansible all -m ping -u bruce --sudo
    
    ansible all -m ping -u bruce --sudo --sudo-user batman
    

    (如果你碰巧想要使用其他sudo的实现方式,你可以通过修改Ansible的配置文件来实现.也可以通过传递标识给sudo(如-H)来设置.) 现在对你的所有节点运行一个命令:

    ansible all -a "/bin/echo hello"
    node1 | CHANGED | rc=0 >>
    hello
    
    node2 | CHANGED | rc=0 >>
    hello
    

    公钥认证

    Ansible1.2.1及其之后的版本都会默认启用公钥认证

    如果有个主机重新安装并在“known_hosts”中有了不同的key,这会提示一个错误信息直到被纠正为止.在使用Ansible时,你可能不想遇到这样的情况:如果有个主机没有在“known_hosts”中被初始化将会导致在交互使用Ansible或定时执行Ansible时对key信息的确认提示.

    如果你想禁用此项行为并明白其含义,你能够通过编辑 /etc/ansible/ansible.cfg or ~/.ansible.cfg来实现:

    [defaults]
    host_key_checking = False
    

    同样注意在paramiko 模式中 公钥认证 相当的慢.因此,当使用这项特性时,切换至’SSH’是推荐做法.

    密码认证

    因为我们接下来要将存取的密码放到主机清单甚至存到Mysql里面,我们可以装一个ssh_pass

    apt-get install sshpass
    

    我们将之前的公钥.ssh目录都删掉,主机名解析不用管.

    注意,删除.ssh目录过后记得关闭主机秘钥检查.

    tail -3 /etc/hosts
    121.36.43.223	node1
    120.77.248.31	node2
    116.196.83.113	master
    
    tail -2  /etc/ansible/hosts 
    node1
    node2
    
    ansible all -m ping -k
    # 并不是真的ping,只是检查客户端的22号端口是否提供工作.不指定用户默认root用户
    # -k 输入密码
    # -m 指定模块
    SSH password: 
    node1 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }
    node2 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }
    # 如果不想指定用户名和密码,避免ansible每次执行到相应主机都会要求输入密码.
    tail -2 /etc/ansible/hosts 
    node1 ansible_ssh_user='root' ansible_ssh_pass='youmen'
    node2 ansible_ssh_user='root' ansible_ssh_pass='youmen'  ansible_ssh_port=22
    
    ansible all -m ping
    node1 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }
    node2 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }
    

    Ansible常用模块

    常用模块

    模块名 作用 用例
    command 默认模块 ansible webserver -a "/sbin/reboot" -f 10
    shell 执行shell命令 ansible test -m shell -a "echo $HOSTNAME"
    filetransfer 文件传输 ansible test -m copy -a "src=/etc/hosts dest=/tmp/hosts"
    managingpackages 管理软件包 ansible test -m yum -a "name=nginx state=present"
    user and groups 用户和组 ansible test -m user -a "name=jeson password=123456"
    Deploying 部署模块 ansible test -m git -a "repo=https://github.com/iopsgroup/imoocc dest=/opt/iops version=HEAD"
    managingservices 服务管理 ansible test -m service -a "name=nginx state=started"
    BackgroundOperatiions 后台运行 ansible test -B 3600 -a "/usr/bin/running_operation --do-stuff"
    gatheringfacts 搜集系统信息 ansible test -m setup

    playbook

    playbook由YAML语言编写,YAML参考了其他多种语言,包括: XML,C语言,Python,Perl以及电子邮件格式RFC2822,Clark Evans在2001年5月首次发表了这种语言,另外Ingy dt Net与Oren-Kiki也是这语言的共同设计者.

    playbook的优势

    # 1. 功能比adhoc更全
    # 2. 控制好依赖
    # 3. 展现更直观
    # 4. 持久使用
    

    ansible-playbook执行常用命令参数:

    执行方式:ansible-playbook playbook.yml [options]

     -u REMOTE_USER, --user=REMOTE_USER  
    # ssh 连接的用户名
     -k, --ask-pass    
    # ssh登录认证密码
     -s, --sudo           
    # sudo 到root用户,相当于Linux系统下的sudo命令
     -U SUDO_USER, --sudo-user=SUDO_USER    
    # sudo 到对应的用户
     -K, --ask-sudo-pass     
    # 用户的密码(—sudo时使用)
     -T TIMEOUT, --timeout=TIMEOUT 
    # ssh 连接超时,默认 10 秒
     -C, --check      
    # 指定该参数后,执行 playbook 文件不会真正去执行,而是模拟执行一遍,然后输出本次执行会对远程主机造成的修改
    
     -e EXTRA_VARS, --extra-vars=EXTRA_VARS    
    # 设置额外的变量如:key=value 形式 或者 YAML or JSON,以空格分隔变量,或用多个-e
    
     -f FORKS, --forks=FORKS    
    # 进程并发处理,默认 5
     -i INVENTORY, --inventory-file=INVENTORY   
    # 指定 hosts 文件路径,默认 default=/etc/ansible/hosts
     -l SUBSET, --limit=SUBSET    
    # 指定一个 pattern,对- hosts:匹配到的主机再过滤一次
     --list-hosts  
    # 只打印有哪些主机会执行这个 playbook 文件,不是实际执行该 playbook
     --list-tasks   
    # 列出该 playbook 中会被执行的 task
    
     --private-key=PRIVATE_KEY_FILE   
    # 私钥路径
     --step    
    # 同一时间只执行一个 task,每个 task 执行前都会提示确认一遍
     --syntax-check  
    # 只检测 playbook 文件语法是否有问题,不会执行该 playbook 
     -t TAGS, --tags=TAGS   
    # 当 play 和 task 的 tag 为该参数指定的值时才执行,多个 tag 以逗号分隔
     --skip-tags=SKIP_TAGS   
    # 当 play 和 task 的 tag 不匹配该参数指定的值时,才执行
     -v, --verbose   
    # 输出更详细的执行过程信息,-vvv可得到所有执行过程信息。
    
    使用场景

    yaml语法

    1. playbook配置
    ---
    - hosts: 39.108.140.0
      remote_user: root
      vars:
       touch_file: youmen.file
      tasks:
      - name: touch file
        shell: "touch /tmp/{{touch_file}}"
    

    yaml主要由三个部分组成:

    > hosts部分:
    # 使用hosts指示使用哪个主机或主机组来运行下面的tasks,
    # 每个playbook都必须指定hosts,hosts也可以使用通配符格式。
    # 主机或主机组在inventory清单中指定,可以使用系统默认的/etc/ansible/hosts,
    # 也可以自己编辑,在运行的时候加上-i选项,指定清单的位置即可。
    # 在运行清单文件的时候,--list-hosts选项会显示那些主机将会参与执行task的过程中。
    
    > remote_user:指定远端主机中的哪个用户来登录远端系统,
    # 在远端系统执行task的用户,可以任意指定,也可以使用sudo,
    # 但是用户必须要有执行相应task的权限。
    
    > tasks:指定远端主机将要执行的一系列动作。tasks的核心为ansible的模块,
    # 前面已经提到模块的用法。tasks包含name和要执行的模块,name是可选的,
    # 只是为了便于用户阅读,不过还是建议加上去,模块是必须的,同时也要给予模块相应的参数。
    

    执行

    ansible-playbook -i /tmp/hosts --list-hosts ./f1.yaml
    ansible-playbook ./f1.yaml
    
    # 执行结果返回
    # 红色: 表示有task执行失败或者提醒的信息
    # 黄色: 表示执行了且改变了远程主机状态
    # 绿色: 表示执行成功
    

    yaml语法和数据结构

    yaml语法

    YAML格式是类似于JSON的文件格式,以便于人理解和阅读,同时便于书写,首先学习了解一下YAML的格式,对我们后面书写playbook很有帮助.
    以下为playbook常用到的YAML格式

    # 大小写敏感
    # 使用缩紧表示层级关系(只能空格不能使用tab)
    # yaml文件以"---"作为文档的开始
    # 在同一行中,#之后的内容表示注释,类似于shell,python和ruby.
    # YAML中的列表元素以"-"开头,然后紧跟着一个空格,后面为元素内容,就像这样
    - apple
    - orange
    等价于JSON的这种格式
    [
     "apple",
     "orange"
    ]
    
    # 同一个列表中的元素应该保持相同的缩进,否则会被当做错误处理.
    # play中hosts,variables,roles,tasks等对象的表示方法都是键值中间以":"分割表示,":"后面还要增加一个空格.
    
    变量定义方式

    变量名可以为字母,数字以及下划线

    playbook里的变量

     1. playbook的yaml文件中定义变量赋值
    > 2. --exxtra-vars执行参数赋给变量
    > 3. 在文件中定义变量
    > 4. 注册变量
    
    # register关键字可以存储指定命令的输出结果到一个自定义的变量中.
    ---
    - hosts: database
      remote_user: root
      vars:
        touch_file: youmen_file
      tasks:
        - name: get date
          command: date
          register: date_output
        - name: touch
          shell: "touch /tmp/{{touch_file}}"
        - name: echo  date_output
          shell: "echo {{date_output.stdout}}>/tmp/{{touch_file}}"
    
    数据结构

    yaml支持的数据结构
    字典

    {name:jeson}
    

    列表

    - Apple
    - Mango
    - Orange
    

    纯量: 数字,布尔,字符串

    条件判断
    循环
    循环类型 关键字
    标准循环 with_items
    嵌套循环 with_nested
    遍历字典 with_dict
    并行遍历列表 with_together
    遍历列表和索引 with_indexed_items
    遍历文件列表的内容 with_file
    遍历目录文件 with_fileglog
    重试循环 until
    查找第一个匹配文件 with_first_found
    随机选择 with_random_choice
    在序列中循环 with_sequence

    条件循环语句复用

    种类一, 标准循环

    ---
    - hosts: nginx
      tasks:
      - name: add serveral users
        user: name={{ item.name }} state=present groups={{ item.groups }}
        with_items:
          - { name: 'testuser1',groups: 'wheel' }
          - { name: 'testuser2',groups: 'root'  }
    

    种类二, 遍历字典

    ---
    - hosts: nginx
      remote_user: root
      tasks:
        - name: add serveral users
          user: name={{ item.key }} state=present groups={{ item.value }}
          with_dict:
            { 'testuser3':'wheel','testuser4':'root' }
    

    种类三, 遍历目录中内容

    ---
    - hosts: nginx
      remote_user: root
      tasks:
       - file: dest=/tmp/aa state=directory
       - copy: src={{ item }} dest=/tmp/bb owner=root mode=600
         with_fileglob:
           - aa/*n
    
    条件语句结合循环语句使用场景
    ---
    - hosts: nginx
      remote_user: root
      tasks:
        - debug: msg="{{ item.key }} is the winner"
          with_dict: {'jeson':{'english':60,'chinese':30},'tom':{'english':20,'chinese':30}}
          when: item.value.english >= 10
    
    异常

    异常处理和相关操作

    异常处理

    1.忽略错误

    默认会检查命令和模块的返回状态,遇到错误就中断playbook的执行
    加入参数: ignore_errors: yes
    Example

    - hosts: nginx
      remote_user: root
      tasks:
        - name: ignore false
          command: /bin/false
          ignore_errors: yes
        - name: touch a file
          file: path=/tmp/test22 state=touch mode=0700 owner=root group=root
    

    2. tags标签处理

    ---
    - hosts: nginx
      remote_user: root
      tasks:
        - name: get process
          shell: touch /tmp/change_test2
          changed_when: false
    

    打标签

    意义: 通过tags和任务对象进行捆绑,控制部分或者指定的task执行

    # 打标签
    # 	对一个对象打一个标签
    # 	对一个对象打多个标签
    # 	打标签的对象包括: 单个task任务,include对象,roles对象等.
    

    标签使用

    -t : 执行指定的tag标签任务
    --skip-tags: 执行 --skip-tags之外的标签任务
    
    1. 自定义change状态
    ---
    - hosts: nginx
      remote_user: root
      tasks:
        - name: get process
          shell: ps -ef |wc -l
          register: process_count
          failed_when: process_count > 3
        - name: touch a file
          file: path=/tmp/test1 state=touch mode=0700 owner=root group=root
    
    roles角色和场景演练

    使用roles角色
    include的用法

    include_tasks/include: 动态的包含tasks任务列表执行
    

    什么是roles

    是一种利用在大型playbook中的剧本配置模式,在这自己特定结构

    为什么需要用到roles

    和面向对象开发思想相似
    利用于大型的项目任务中,尽可能的将公共的任务,变量等内容独立

    剧本结构和设计思路
    ansible官方网站的建议playbook剧本结构如下:

    production        # 正式环境的inventory文件
    staging           #测试环境用得inventory文件
    group_vars/  	  # 机器组的变量文件
          group1        
          group2
    host_vars/   	 #执行机器成员的变量
          hostname1     
          hostname2
    ================================================
    site.yml               # 主要的playbook剧本
    webservers.yml         # webserver类型服务所用的剧本
    dbservers.yml          # 数据库类型的服务所用的剧本
    
    roles/
          webservers/        #webservers这个角色相关任务和自定义变量
               tasks/
                   main.yml
               handlers/
                   main.yml
               vars/            
                    main.yml
            dbservers/         #dbservers这个角色相关任务和定义变量
                ...
          common/       	  # 公共的
               tasks/        
                    main.yml    
               handlers/    
                    main.yml    # handlers file.
               vars/            # 角色所用到的变量
                    main.yml    # 
    ===============================================
          templates/    #
                ntp.conf.j2 # 模版文件
          files/        #   用于上传存放文件的目录
                bar.txt     
                foo.sh     
          meta/         # 角色的依赖
                main.yml   
    
    场景演练

    Nginx工程方式的编译安装

    # 剧本分解
    ansible.cfg
      - files		#	存放上传文件
        - index.html
        - nginx    # 系统init中,控制nginx启动脚本
        - nginx-1.12.2.tar.gz  # nginx的安装包文件
    
    production	  # 线上的主机配置文件
    roles		  # roles角色执行
      - apache
      - common
         tasks
           main.yml
         vars
    	main.yml
        meta
        nginx
          - handlers   通过notify触发
            main.yml
          - tasks
    	  - basic.yml
    	  - main.yml
    	 - nginx.yml
          - vars
    	= main.yml
        tasks
    
    staging			线下测试环境使用的主机配置文件
      - templates		模板(配置,html)
        - nginx1.conf	nginx的自定义conf文件
    webserver.yaml		web服务相关主执行文件
    

    Ansible的核心类介绍

    核心类 用途 所在的模块路径
    DataLoader 用于读取yaml,json格式的文件 ansible.parsing.dataloader
    Play 存储执行hosts的角色信息 ansible.playbook.play
    TaskQueueManager ansible底层用到的任务队列 ansible.executor.task_queue_manager
    PlaybookExecutor 核心累执行playbook剧本 ansible.executor.playbook_executor
    CallbackBase 状态回调,各种成功失败的状态 ansible.plugins.callback
    InventoryManager 用于导入inventory文件 ansible.inventory.manager
    VariableManager 用于存储各类变量信息 ansible.vars.manager
    Host,Group 用于操作单个主机或者主机组信息 ansible.inventory.host
    InventoryManager

    用来管理主机和主机组信息

    from ansible.parsing.dataloader import DataLoader
    from ansible.inventory.manager import InventoryManager
    
    # InventoryManager类
    loader = DataLoader()
    InventoryManager(loader=loader,sources=['youmen_hosts'])
    
    # 1. 添加主机到指定主机组 add_host()  
    # 2. 查看主机组资源get_groups_dict()  
    # 3. 获取指定的主机对象get_host()
    
    # VariableManager类
    # loader: 实例对象
    # inventory: 调用InventoryManager返回的实例对象.
    VariableManager(loader=loader,inventory=inventory)
    
    # 查看主机变量方法 get_vars()
    # 设置主机变量方法set_host_variable()
    # 添加扩展变量extra_vars
    
    ad-hoc模式调用场景

    ansible -m command -a "ls /tmp" testgroup -i /etc/ansible/hosts -f 5

  • 相关阅读:
    js下拉框二级关联菜单效果代码具体实现
    js实现拉伸拖动iframe的具体代码
    mysql--Ubuntu下设置MySQL字符集为utf8
    python--使用MySQL数据库
    python--笨方法学python 习题52
    python--web.py使用
    python--flask使用
    python--类方法、对象方法、静态方法
    Python--类定义
    堆 在游戏中的运用
  • 原文地址:https://www.cnblogs.com/you-men/p/13153462.html
Copyright © 2011-2022 走看看